{
  "openapi": "3.0.0",
  "info": {
    "version": "3.0.0",
    "title": "Didit Verification API",
    "description": "API de vérification d'identité. Authentifiez-vous avec l'en-tête x-api-key."
  },
  "servers": [
    {
      "url": "https://verification.didit.me"
    }
  ],
  "tags": [],
  "paths": {
    "/system/healthcheck": {
      "get": {
        "summary": "Bilan de santé du service (public, non authentifié)",
        "description": "Sonde de vivacité publique non authentifiée. Renvoie `HTTP 200` avec `{status: \"ok\", timestamp}` lorsque le service, la base de données, le cache et le broker sont opérationnels.",
        "operationId": "get_system_healthcheck",
        "x-didit-sdk": {
          "resource": "system",
          "method": "healthcheck",
          "auth": "public",
          "server": false
        },
        "tags": [
          "System"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Le service est opérationnel et accepte les requêtes. Le corps est toujours `{\"status\": \"ok\", \"timestamp\": \"<iso8601>\"}`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "timestamp"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ],
                      "description": "Marqueur de détection du vivant. Toujours la chaîne littérale `\"ok\"` sur une réponse 200.",
                      "example": "ok"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Heure du serveur à laquelle l'état de santé a été évalué, au format ISO 8601 avec une précision à la milliseconde et un suffixe `Z` (UTC).",
                      "example": "2026-04-21T16:42:50.445Z"
                    }
                  }
                },
                "examples": {
                  "Healthy": {
                    "summary": "Le service est opérationnel",
                    "value": {
                      "status": "ok",
                      "timestamp": "2026-04-21T16:42:50.445Z"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Le service est défaillant — l'un des plugins de vérification de l'état configurés (base de données, cache, broker) est en échec. Le corps de la réponse est intentionnellement minimal ; le code HTTP est le signal déterminant. Réessayez avec une temporisation exponentielle."
          },
          "5XX": {
            "description": "Le service de vérification est dégradé ou inaccessible. Considérez toute réponse non-2xx comme « non sain » et réessayez avec un backoff exponentiel."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -i https://verification.didit.me/system/healthcheck"
          },
          {
            "lang": "Python",
            "label": "Python (requests)",
            "source": "import requests\n\nresp = requests.get(\"https://verification.didit.me/system/healthcheck\", timeout=5)\nresp.raise_for_status()\nprint(resp.json())  # {'status': 'ok', 'timestamp': '2026-04-21T16:42:50.445Z'}"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js (fetch)",
            "source": "const res = await fetch(\"https://verification.didit.me/system/healthcheck\");\nif (!res.ok) throw new Error(`Didit unhealthy: ${res.status}`);\nconst body = await res.json();\nconsole.log(body); // { status: 'ok', timestamp: '2026-04-21T16:42:50.445Z' }"
          }
        ]
      }
    },
    "/v3/email/risk/": {
      "post": {
        "summary": "Calculer le score de risque d'une adresse e-mail",
        "description": "Renvoie les signaux de délivrabilité, d'adresse jetable, de fuite de données, de correspondance inter-sessions et de renseignements normalisés sur les risques sans envoyer d'OTP. L'endpoint crée une session d'API et renvoie son identifiant sous forme de `request_id`.\n\n**Décision.** Le `status` de premier niveau reflète `email.status`. Il vaut normalement `Approved` ; l'évaluation des risques peut produire `In Review` ou `Declined`.\n\n**Alias de compatibilité.** Les réponses en production exposent l'objet de renseignements normalisé à la fois sous `email.email_intelligence` et `email.enrichment`. Les valeurs sont identiques. Les nouvelles intégrations peuvent lire `email.enrichment`. Les deux clés sont absentes lorsqu'aucune donnée de renseignement exploitable n'a été renvoyée.\n\n**Facturation.** Les appels en production utilisent les tarifs de l'Email Risk API. La requête est facturable dès que la recherche commence, même si certains champs fournis au mieux sont indisponibles.\n\n**Sandbox.** Les clés de sandbox valident la requête et renvoient des données approuvées déterministes sans envoyer d'e-mail, consommer de crédits, créer de session ni contribuer à Networks.\n\n**Authentification.** Envoyez la clé API de votre application dans `x-api-key`. Des identifiants manquants ou invalides renvoient `403` - cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes par minute par clé API sur les endpoints POST/PATCH/DELETE (les créations de transactions et l'ingestion d'événements disposent d'un budget distinct de 600).\n\n**Empreinte sociale.** Définissez `enable_social` sur `true` pour ajouter un bloc `email_social` : les plateformes en ligne sur lesquelles cette adresse est enregistrée, avec le décompte par catégorie et les détails de profil disponibles. `profiles_registered: 0` signifie que les plateformes ont été vérifiées et que l'adresse n'a été trouvée sur aucune d'entre elles - une réponse valide et facturable. Le bloc est absent lorsque l'option n'a pas été demandée ou que la vérification n'a pas pu être effectuée, et il n'est pas facturé dans ce cas. La facturation ajoute une unité `email_social` par requête en plus du prix propre à cet endpoint.",
        "operationId": "post_v3email_risk",
        "x-didit-sdk": {
          "resource": "email",
          "method": "assess_risk",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/email/risk/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"email\": \"alice@example.com\",\n    \"country_code\": \"US\",\n    \"vendor_data\": \"lead-123\",\n    \"metadata\": {\"source\": \"signup_prescreen\"}\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.email.assess_risk(\n    email=\"alice@example.com\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.email.assessRisk({\n  email: \"alice@example.com\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Email.AssessRisk(ctx, didit.EmailRiskRequest{\n\tEmail: \"alice@example.com\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.EmailRiskRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.email().assessRisk(EmailRiskRequest.builder()\n        .email(\"alice@example.com\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->email->assessRisk([\n    'email' => 'alice@example.com',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.email.assess_risk(email: \"alice@example.com\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Email.AssessRiskAsync(new EmailRiskRequest\n{\n    Email = \"alice@example.com\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailRiskRequest"
              },
              "examples": {
                "Minimal": {
                  "summary": "Évaluer une adresse avec les paramètres par défaut",
                  "value": {
                    "email": "alice@example.com"
                  }
                },
                "Full context": {
                  "summary": "Évaluer avec des signaux, une indication de pays et des identifiants de corrélation",
                  "value": {
                    "email": "alice@example.com",
                    "country_code": "US",
                    "signals": {
                      "ip": "192.0.2.1",
                      "device_id": "8F0B8FDD-C2CB-4387-B20A-56E9B2E5A0D2",
                      "device_platform": "web",
                      "os_version": "14.4",
                      "app_version": "1.2.34",
                      "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15"
                    },
                    "vendor_data": "lead-123",
                    "metadata": {
                      "source": "signup_prescreen"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "L'évaluation du risque est terminée. Inspectez `status` pour connaître la décision ; le code HTTP est toujours `200` pour les recherches terminées.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailRiskResponse"
                },
                "examples": {
                  "Clean address": {
                    "summary": "Adresse livrable sans exposition à une compromission",
                    "value": {
                      "request_id": "82397be9-5921-4970-a979-2d5b43e08b33",
                      "status": "Approved",
                      "email": {
                        "status": "Approved",
                        "email": "alice@example.com",
                        "is_breached": false,
                        "breaches": [],
                        "is_disposable": false,
                        "is_undeliverable": false,
                        "verification_attempts": 0,
                        "verified_at": null,
                        "warnings": [],
                        "lifecycle": [],
                        "matches": [],
                        "email_intelligence": {
                          "score": 4.0,
                          "deliverable": "high",
                          "breach_risk_level": "Low",
                          "breach_risk_index": 4,
                          "is_recent_breach": false,
                          "is_frequent_breached": false,
                          "is_disposable": false,
                          "is_free_domain": false,
                          "is_breached": false,
                          "no_of_breaches": 0,
                          "reason_codes": []
                        },
                        "enrichment": {
                          "score": 4.0,
                          "deliverable": "high",
                          "breach_risk_level": "Low",
                          "breach_risk_index": 4,
                          "is_recent_breach": false,
                          "is_frequent_breached": false,
                          "is_disposable": false,
                          "is_free_domain": false,
                          "is_breached": false,
                          "no_of_breaches": 0,
                          "reason_codes": []
                        }
                      },
                      "vendor_data": "lead-123",
                      "metadata": {
                        "source": "signup_prescreen"
                      },
                      "created_at": "2026-09-01T10:30:00.123456+00:00"
                    }
                  },
                  "Breached address": {
                    "summary": "Adresse trouvée dans des fuites de données connues",
                    "value": {
                      "request_id": "d1e5c2a8-6f30-4c1a-8b2d-3e4f5a6b7c8d",
                      "status": "In Review",
                      "email": {
                        "status": "In Review",
                        "email": "bob@example.org",
                        "is_breached": true,
                        "breaches": [
                          {
                            "name": "ExampleBreach2023",
                            "domain": "example.org",
                            "breach_date": "2023-06-01",
                            "breach_emails_count": 1200000,
                            "description": "A data breach affecting example.org accounts.",
                            "logo_path": "https://logos.example.org/example.png",
                            "data_classes": [
                              "email_addresses",
                              "passwords"
                            ],
                            "is_verified": true
                          }
                        ],
                        "is_disposable": false,
                        "is_undeliverable": false,
                        "verification_attempts": 0,
                        "verified_at": null,
                        "warnings": [],
                        "lifecycle": [],
                        "matches": [],
                        "email_intelligence": {
                          "score": 58.0,
                          "deliverable": "high",
                          "breach_risk_level": "High",
                          "breach_risk_index": 72,
                          "is_recent_breach": true,
                          "is_frequent_breached": true,
                          "is_disposable": false,
                          "is_free_domain": true,
                          "is_breached": true,
                          "no_of_breaches": 4,
                          "reason_codes": [
                            {
                              "code": "IR-F784B630",
                              "direction": "risk",
                              "message": "Email's digital footprint diversity is Very Low",
                              "impact_level": "low"
                            }
                          ]
                        },
                        "enrichment": {
                          "score": 58.0,
                          "deliverable": "high",
                          "breach_risk_level": "High",
                          "breach_risk_index": 72,
                          "is_recent_breach": true,
                          "is_frequent_breached": true,
                          "is_disposable": false,
                          "is_free_domain": true,
                          "is_breached": true,
                          "no_of_breaches": 4,
                          "reason_codes": [
                            {
                              "code": "IR-F784B630",
                              "direction": "risk",
                              "message": "Email's digital footprint diversity is Very Low",
                              "impact_level": "low"
                            }
                          ]
                        }
                      },
                      "vendor_data": "lead-125",
                      "metadata": null,
                      "created_at": "2026-09-01T10:30:00.123456+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/EmailRiskValidationError"
          },
          "403": {
            "$ref": "#/components/responses/RiskPermissionDenied"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/ip/risk/": {
      "post": {
        "summary": "Calculer le score de risque d'une adresse IP",
        "description": "Renvoie la géolocalisation, la propriété du réseau, les indicateurs VPN/Tor et centre de données, les données sur les menaces et `country_mismatch` pour une adresse IP fournie. L'endpoint crée une session d'API et renvoie son identifiant sous forme de `request_id`.\n\n**Décision.** `status` est `In Review` lorsque le pays résolu entre en conflit avec `claimed_country`, ou lorsque l'adresse est associée à une infrastructure VPN, Tor ou de centre de données. Sinon, il vaut `Approved`.\n\n**Au mieux.** L'enrichissement d'IP est fourni au mieux. Si aucune source d'enrichissement ne renvoie de données exploitables, l'endpoint renvoie une réponse approuvée avec `ip.ip_address: null`, `ip.country_mismatch: null` et un objet `ip.threat` vide.\n\n**Facturation.** Les appels en production utilisent les tarifs de l'IP Risk API. La requête est facturable dès que la recherche commence.\n\n**Sandbox.** Les clés de sandbox valident la requête et renvoient des données approuvées déterministes sans consommer de crédits, créer de session ni contribuer à Networks.\n\n**Authentification.** Envoyez la clé API de votre application dans `x-api-key`. Des identifiants manquants ou invalides renvoient `403` - cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes par minute par clé API sur les endpoints POST/PATCH/DELETE (les créations de transactions et l'ingestion d'événements disposent d'un budget distinct de 600).",
        "operationId": "post_v3ip_risk",
        "x-didit-sdk": {
          "resource": "ip",
          "method": "assess_risk",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/ip/risk/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"ip_address\": \"8.8.8.8\",\n    \"claimed_country\": \"ESP\",\n    \"user_agent\": \"Mozilla/5.0\",\n    \"vendor_data\": \"lead-123\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.ip.assess_risk(\n    ip_address=\"8.8.8.8\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.ip.assessRisk({\n  ip_address: \"8.8.8.8\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IP.AssessRisk(ctx, didit.IPRiskRequest{\n\tIPAddress: \"8.8.8.8\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.IPRiskRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.ip().assessRisk(IPRiskRequest.builder()\n        .ipAddress(\"8.8.8.8\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->ip->assessRisk([\n    'ip_address' => '8.8.8.8',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.ip.assess_risk(ip_address: \"8.8.8.8\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Ip.AssessRiskAsync(new IPRiskRequest\n{\n    IpAddress = \"8.8.8.8\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IPRiskRequest"
              },
              "examples": {
                "Minimal": {
                  "summary": "Évaluer une adresse avec les paramètres par défaut",
                  "value": {
                    "ip_address": "8.8.8.8"
                  }
                },
                "With claimed country": {
                  "summary": "Évaluer avec un pays déclaré pour la détection de discordance",
                  "value": {
                    "ip_address": "8.8.8.8",
                    "claimed_country": "ESP",
                    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15",
                    "vendor_data": "lead-123"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "L'évaluation du risque est terminée. Inspectez `status` pour connaître la décision ; le code HTTP est toujours `200` pour les recherches terminées.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IPRiskResponse"
                },
                "examples": {
                  "Clean residential IP": {
                    "summary": "Adresse résidentielle, le pays déclaré correspond",
                    "value": {
                      "request_id": "9a96ed2a-721e-4b86-8cbf-d61eda529279",
                      "status": "Approved",
                      "ip": {
                        "status": "Approved",
                        "ip_address": "192.0.2.10",
                        "ip_country": "Spain",
                        "ip_country_code": "ES",
                        "ip_state": "Madrid",
                        "ip_city": "Madrid",
                        "latitude": 40.4168,
                        "longitude": -3.7038,
                        "isp": "Example Telecom",
                        "organization": "Example Telecom SA",
                        "is_vpn_or_tor": false,
                        "is_data_center": false,
                        "time_zone": "Europe/Madrid",
                        "time_zone_offset": "+0200",
                        "asn_number": 3352,
                        "asn_organization": "EXAMPLE-TELECOM",
                        "connection_type": "broadband",
                        "carrier": "Example Telecom",
                        "proxy_type": null,
                        "claimed_country": "ESP",
                        "country_mismatch": false,
                        "threat": {}
                      },
                      "vendor_data": "lead-123",
                      "metadata": null,
                      "created_at": "2026-09-01T10:30:00.123456+00:00"
                    }
                  },
                  "Datacenter mismatch": {
                    "summary": "Adresse du centre de données en conflit avec le pays déclaré",
                    "value": {
                      "request_id": "5b1d4e9a-3c7b-4f8e-9a2d-1b0c9d8e7f6a",
                      "status": "In Review",
                      "ip": {
                        "status": "In Review",
                        "ip_address": "8.8.8.8",
                        "ip_country": "United States",
                        "ip_country_code": "US",
                        "ip_state": "California",
                        "ip_city": "Mountain View",
                        "latitude": 37.386,
                        "longitude": -122.0838,
                        "isp": "Google",
                        "organization": "Google LLC",
                        "is_vpn_or_tor": true,
                        "is_data_center": true,
                        "time_zone": "America/Los_Angeles",
                        "time_zone_offset": "-0700",
                        "asn_number": 15169,
                        "asn_organization": "GOOGLE, US",
                        "connection_type": "hosting",
                        "carrier": null,
                        "proxy_type": "VPN",
                        "claimed_country": "ESP",
                        "country_mismatch": true,
                        "threat": {
                          "is_proxy": true,
                          "is_data_center": true,
                          "is_tor": false
                        }
                      },
                      "vendor_data": "lead-126",
                      "metadata": null,
                      "created_at": "2026-09-01T10:30:00.123456+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/IPRiskValidationError"
          },
          "403": {
            "$ref": "#/components/responses/RiskPermissionDenied"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/phone/risk/": {
      "post": {
        "summary": "Calculer le score de risque d'un numéro de téléphone",
        "description": "Résolvez un numéro de téléphone et obtenez l'opérateur, le type de ligne, la portabilité, le caractère jetable du numéro, la correspondance entre sessions et des signaux normalisés de renseignements sur les risques sans envoyer d'OTP. L'endpoint crée une session d'API et renvoie son identifiant sous le nom `request_id`.\n\n**Décision.** Le champ de premier niveau `status` reflète `phone.status`. Il est normalement défini sur `Approved` ; l'évaluation des risques peut produire `In Review` ou `Declined`.\n\n**Alias de compatibilité.** Les réponses en production exposent l'objet de renseignements normalisé à la fois sous `phone.phone_intelligence` et `phone.enrichment`. Les valeurs sont identiques. Les nouvelles intégrations peuvent lire `phone.enrichment`. Les deux clés sont absentes lorsqu'aucune donnée de renseignement exploitable n'a été renvoyée.\n\n**Facturation.** Les appels en production appliquent les tarifs de l'API Phone Risk. La requête est facturable dès que la recherche commence, même si certains champs fournis au mieux sont indisponibles.\n\n**Sandbox.** Les clés sandbox valident la requête et renvoient des données approuvées déterministes sans envoyer d'OTP, consommer de crédits, créer de session ni alimenter Networks.\n\n**Authentification.** Envoyez la clé API de votre application dans `x-api-key`. Des identifiants manquants ou non valides renvoient `403` - cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes par minute par clé API sur les endpoints POST/PATCH/DELETE (la création de transactions et l'ingestion d'événements disposent d'un budget distinct de 600).\n\n**Empreinte sociale.** Définissez `enable_social` sur `true` pour ajouter un bloc `phone_social` : les plateformes en ligne sur lesquelles ce numéro est enregistré, avec les décomptes par catégorie et tous les détails de profil disponibles. `profiles_registered: 0` signifie que les plateformes ont été vérifiées et que le numéro n'a été trouvé sur aucune d'entre elles - une réponse valide et facturable. Le bloc est absent lorsque l'option n'a pas été demandée ou que la vérification n'a pas pu aboutir, et il n'est pas facturé dans ce cas. La facturation ajoute une unité `phone_social` par requête en plus du prix propre à cet endpoint.",
        "operationId": "post_v3phone_risk",
        "x-didit-sdk": {
          "resource": "phone",
          "method": "assess_risk",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/phone/risk/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"phone_number\": \"+14155552671\",\n    \"country_code\": \"US\",\n    \"vendor_data\": \"lead-123\",\n    \"metadata\": {\"source\": \"signup_prescreen\"}\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.phone.assess_risk(\n    phone_number=\"+14155552671\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.phone.assessRisk({\n  phone_number: \"+14155552671\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Phone.AssessRisk(ctx, didit.PhoneRiskRequest{\n\tPhoneNumber: \"+14155552671\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.PhoneRiskRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.phone().assessRisk(PhoneRiskRequest.builder()\n        .phoneNumber(\"+14155552671\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->phone->assessRisk([\n    'phone_number' => '+14155552671',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.phone.assess_risk(phone_number: \"+14155552671\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Phone.AssessRiskAsync(new PhoneRiskRequest\n{\n    PhoneNumber = \"+14155552671\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhoneRiskRequest"
              },
              "examples": {
                "Minimal": {
                  "summary": "Évaluer un numéro avec les paramètres par défaut",
                  "value": {
                    "phone_number": "+14155552671"
                  }
                },
                "Full context": {
                  "summary": "Évaluer avec des signaux, une indication de pays et des identifiants de corrélation",
                  "value": {
                    "phone_number": "+14155552671",
                    "country_code": "US",
                    "signals": {
                      "ip": "192.0.2.1",
                      "device_id": "8F0B8FDD-C2CB-4387-B20A-56E9B2E5A0D2",
                      "device_platform": "ios",
                      "device_model": "iPhone17,2",
                      "os_version": "18.0.1",
                      "app_version": "1.2.34",
                      "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"
                    },
                    "vendor_data": "lead-123",
                    "metadata": {
                      "source": "signup_prescreen"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "L'évaluation du risque est terminée. Inspectez `status` pour connaître la décision ; le code HTTP est toujours `200` pour les recherches terminées.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneRiskResponse"
                },
                "examples": {
                  "Clean mobile number": {
                    "summary": "Numéro de mobile propre avec couverture des renseignements",
                    "value": {
                      "request_id": "4fd09d2e-9bc9-4c4e-9c46-7f625ac0ab62",
                      "status": "Approved",
                      "phone": {
                        "status": "Approved",
                        "phone_number_prefix": "+1",
                        "phone_number": "4155552671",
                        "full_number": "+14155552671",
                        "country_code": "US",
                        "country_name": "United States",
                        "carrier": {
                          "name": "Example Mobile",
                          "type": "mobile"
                        },
                        "is_disposable": false,
                        "is_virtual": false,
                        "verification_method": null,
                        "verification_attempts": 0,
                        "verified_at": null,
                        "warnings": [],
                        "lifecycle": [],
                        "matches": [],
                        "phone_intelligence": {
                          "score": 3.0,
                          "phone_type_risk": "Low",
                          "phone_trust_index": 97,
                          "network_stability_index": 95,
                          "is_disposable": false,
                          "is_ported": false,
                          "is_recently_ported": false,
                          "carrier_type": "mobile",
                          "reason_codes": []
                        },
                        "enrichment": {
                          "score": 3.0,
                          "phone_type_risk": "Low",
                          "phone_trust_index": 97,
                          "network_stability_index": 95,
                          "is_disposable": false,
                          "is_ported": false,
                          "is_recently_ported": false,
                          "carrier_type": "mobile",
                          "reason_codes": []
                        }
                      },
                      "vendor_data": "lead-123",
                      "metadata": {
                        "source": "signup_prescreen"
                      },
                      "created_at": "2026-09-01T10:30:00.123456+00:00"
                    }
                  },
                  "Number in review": {
                    "summary": "Numéro jetable ou virtuel signalé pour examen",
                    "value": {
                      "request_id": "8c22e1f0-4b3d-4a3a-9d1e-2f6b7c8d9e0f",
                      "status": "In Review",
                      "phone": {
                        "status": "In Review",
                        "phone_number_prefix": "+44",
                        "phone_number": "7700900123",
                        "full_number": "+447700900123",
                        "country_code": "GB",
                        "country_name": "United Kingdom",
                        "carrier": {
                          "name": "Example VoIP",
                          "type": "voip"
                        },
                        "is_disposable": true,
                        "is_virtual": true,
                        "verification_method": null,
                        "verification_attempts": 0,
                        "verified_at": null,
                        "warnings": [],
                        "lifecycle": [],
                        "matches": [],
                        "phone_intelligence": {
                          "score": 72.0,
                          "phone_type_risk": "High",
                          "phone_trust_index": 28,
                          "network_stability_index": 40,
                          "is_disposable": true,
                          "is_ported": true,
                          "is_recently_ported": true,
                          "carrier_type": "voip",
                          "reason_codes": [
                            {
                              "code": "IR-5AC67A32",
                              "direction": "risk",
                              "message": "Phone type identified as non-mobile",
                              "impact_level": "medium"
                            }
                          ]
                        },
                        "enrichment": {
                          "score": 72.0,
                          "phone_type_risk": "High",
                          "phone_trust_index": 28,
                          "network_stability_index": 40,
                          "is_disposable": true,
                          "is_ported": true,
                          "is_recently_ported": true,
                          "carrier_type": "voip",
                          "reason_codes": [
                            {
                              "code": "IR-5AC67A32",
                              "direction": "risk",
                              "message": "Phone type identified as non-mobile",
                              "impact_level": "medium"
                            }
                          ]
                        }
                      },
                      "vendor_data": "lead-124",
                      "metadata": null,
                      "created_at": "2026-09-01T10:30:00.123456+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/PhoneRiskValidationError"
          },
          "403": {
            "$ref": "#/components/responses/RiskPermissionDenied"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/": {
      "post": {
        "summary": "Créer une session de vérification",
        "description": "Créez une session de vérification des utilisateurs (KYC) ou de vérification d'entreprise (KYB) et recevez une `url` de vérification hébergée ainsi qu'un `session_token` pour rediriger votre utilisateur final vers cette page ou l'intégrer directement. Le `workflow_id` détermine les étapes de vérification exécutées et si la session est de type KYC ou KYB.\n\nAppelez cet endpoint depuis votre backend (jamais depuis le navigateur — la clé API est secrète) chaque fois qu'un utilisateur ou une entreprise doit être vérifié : lors de l'inscription, avant une action sensible ou lorsqu'une revérification est requise. Prérequis : un workflow publié (créé sur la page [Workflows](https://docs.didit.me/fr/console/workflows) de la Console) et une clé API d'application disposant de crédits. Les applications sandbox contournent la vérification des crédits.\n\n**Idempotence :** lorsque `vendor_data` est fourni et qu'une session inachevée (`Not Started`, `In Progress`, `Resubmitted` ou `Awaiting User`) avec le même `vendor_data` existe déjà sur la **dernière version publiée actuelle** du workflow (et que cette session dispose déjà d'une URL de vérification hébergée), la session existante est renvoyée (toujours en `201`) au lieu de créer un doublon — avec son `callback` et ses `metadata` mis à jour selon les nouvelles valeurs fournies. Une session inachevée créée sur une version antérieure du workflow (qui a été republiée depuis) n'est **pas** réutilisée ; une nouvelle session rattachée à la dernière version publiée est créée à la place. Les sessions avec le statut `Approved`, `Declined`, `In Review`, `Expired`, `Abandoned` ou `Kyc Expired` ne sont jamais réutilisées.\n\n**Effets secondaires :** l'URL de vérification hébergée est générée et stockée ; si `contact_details.send_notification_emails` est défini sur `true` et qu'une adresse e-mail est fournie, un e-mail d'invitation à la vérification est envoyé. La session expire après la durée d'expiration configurée pour le workflow. Pour les workflows KYB, `contact_details.phone` et `expected_details` sont ignorés.",
        "operationId": "post_v3_session_create",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "responses": {
          "201": {
            "description": "Session créée (ou renvoyée, si une session non terminée avec les mêmes `vendor_data` existe déjà sur la dernière version publiée du workflow). La réponse est la session sérialisée, incluant l'`url` de vérification hébergée vers laquelle rediriger l'utilisateur.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "session_id",
                    "session_number",
                    "session_token",
                    "url",
                    "vendor_data",
                    "metadata",
                    "status",
                    "workflow_id",
                    "workflow_version",
                    "callback"
                  ],
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant unique de la session de vérification. Utilisez cet identifiant lors de l'appel à `GET /v3/session/{sessionId}/decision/`.",
                      "example": "11111111-2222-3333-4444-555555555555"
                    },
                    "session_number": {
                      "type": "integer",
                      "description": "Numéro séquentiel et lisible attribué à la session au sein de votre application. Utile pour le support et les tableaux de bord.",
                      "example": 43762
                    },
                    "session_token": {
                      "type": "string",
                      "description": "Token de 12 caractères compatible avec les URL autorisant l'utilisateur final à accéder au flux de vérification hébergé à `url`. Valide jusqu'à l'expiration de la session. Traitez-le comme un secret — toute personne en sa possession peut ouvrir le flux de vérification pour cette session.",
                      "example": "3FaJ9wLqX2Mz"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "URL de vérification hébergée vers laquelle rediriger l'utilisateur final. L'URL intègre le `session_token` et, si configuré, utilise votre domaine en marque blanche. Lorsque la requête comprend `language`, l'URL contient un segment de chemin de langue — `https://verify.didit.me/{language}/session/{session_token}` (par exemple `/es/session/...`) ; sans `language`, ce segment est omis.",
                      "example": "https://verify.didit.me/session/3FaJ9wLqX2Mz"
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Identifiant que vous avez transmis dans la requête pour lier la session à un utilisateur ou une entreprise dans votre propre système. Renvoyé textuellement. Null lorsqu'il n'est pas fourni.",
                      "example": "user-123"
                    },
                    "metadata": {
                      "description": "Payload JSON arbitraire que vous avez stocké avec la session au moment de sa création. Renvoyé textuellement — quelle que soit la valeur JSON envoyée (objet, chaîne, nombre, tableau), elle est retournée telle quelle, bien qu'un objet JSON soit recommandé. Non visible par l'utilisateur final. Toujours présent dans les réponses ; `null` lorsqu'il n'a pas été fourni lors de la création.",
                      "example": {
                        "user_type": "premium",
                        "account_id": "ABC123"
                      }
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Les étiquettes sur la session, par nom.",
                      "example": [
                        "VIP",
                        "ONBOARDING Q4"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "Not Started",
                        "In Progress",
                        "Approved",
                        "Declined",
                        "In Review",
                        "Expired",
                        "Abandoned",
                        "Kyc Expired",
                        "Resubmitted",
                        "Awaiting User"
                      ],
                      "description": "Statut actuel de la session. Les sessions nouvellement créées renvoient `Not Started`. Si une session non terminée existait déjà pour le même `vendor_data` sur la dernière version publiée du workflow, le statut renvoyé reflète cette session existante.",
                      "example": "Not Started"
                    },
                    "callback": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de redirection finale vers laquelle l'utilisateur est renvoyé après avoir terminé le flux. Didit ajoute `?verificationSessionId={session_id}&status={status}` à cette URL. Se rabat sur l'URL de rappel configurée du workflow si elle n'est pas fournie dans la requête ; `null` si aucune n'est définie. Lorsque l'application a des domaines autorisés et que cette URL est une URL web en dehors de ceux-ci (par exemple une valeur par défaut de workflow définie avant la modification de la liste), le flux hébergé n'y redirige pas l'utilisateur.",
                      "example": "https://example.com/verification/callback"
                    },
                    "workflow_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant stable du workflow sur lequel s'exécute cette session. Il s'agit toujours de l'identifiant de groupe stable du workflow — même si vous avez référencé un UUID de version de workflow spécifique dans la requête (recherche rétrocompatible), la réponse contient le `workflow_id` stable. Utilisez-le pour corréler la session avec le workflow que vous avez configuré dans la Console.",
                      "example": "11111111-2222-3333-4444-555555555555"
                    },
                    "workflow_version": {
                      "type": "integer",
                      "description": "Numéro de version de la version publiée du workflow à laquelle la session a été associée lors de sa création. Didit résout `workflow_id` vers la dernière version publiée du workflow lorsque la session est créée, et la session continue d'exécuter cette version même si le workflow est republié ultérieurement.",
                      "example": 3
                    }
                  }
                },
                "examples": {
                  "KYC session": {
                    "summary": "Session KYC créée",
                    "value": {
                      "session_id": "11111111-2222-3333-4444-555555555555",
                      "session_number": 43762,
                      "session_token": "3FaJ9wLqX2Mz",
                      "url": "https://verify.didit.me/en/session/3FaJ9wLqX2Mz",
                      "vendor_data": "user-123",
                      "metadata": {
                        "user_type": "premium",
                        "account_id": "ABC123"
                      },
                      "status": "Not Started",
                      "workflow_id": "11111111-2222-3333-4444-555555555555",
                      "workflow_version": 3,
                      "callback": "https://example.com/verification/callback"
                    }
                  },
                  "KYB session": {
                    "summary": "Session KYB créée",
                    "value": {
                      "session_id": "22222222-3333-4444-5555-666666666666",
                      "session_number": 43763,
                      "session_token": "Yk7pQ2vN8aBc",
                      "url": "https://verify.didit.me/en/session/Yk7pQ2vN8aBc",
                      "vendor_data": "company-acme-001",
                      "metadata": {
                        "tier": "enterprise"
                      },
                      "status": "Not Started",
                      "workflow_id": "33333333-4444-5555-6666-777777777777",
                      "workflow_version": 1,
                      "callback": "https://example.com/kyb/callback"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Requête incorrecte — le payload a échoué à la validation (`workflow_id` manquant ou inconnu, `language` non valide, `vendor_data` sur liste de blocage, `portrait_image` mal formée, `address` sans `country`/`poa_country`, `sandbox_scenario` non valide, documents, champs ou valeurs `sign` que l'étape de Signature électronique du workflow refuse, tels que `signature_document_not_supported`, `signature_document_conversion_failed`, `field_anchor_not_found` ou `field_value_missing`, etc.) ou votre organisation n'a pas assez de crédits pour démarrer la session.\n\nLe corps est un objet indexé par le nom du champ en cause (ou `detail` pour les erreurs non liées à un champ précis). Les valeurs sont un **tableau de chaînes** pour les échecs de validation des entrées (par ex. champ obligatoire manquant, langue non valide, image de portrait trop volumineuse) et une **chaîne simple** pour les erreurs détectées lors de la création de la session (`workflow_id` inconnu, `vendor_data` sur liste de blocage, aucun visage de référence disponible pour un workflow de Correspondance faciale). Gérez les deux formats.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain pour les erreurs non liées à un champ (par ex. crédits insuffisants). Les échecs au niveau d'un champ utilisent plutôt le nom du champ comme clé, avec une valeur sous forme de chaîne ou de tableau de chaînes.",
                      "example": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                },
                "examples": {
                  "Missing workflow_id": {
                    "summary": "Champ obligatoire omis (format tableau de chaînes)",
                    "value": {
                      "workflow_id": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid workflow_id": {
                    "summary": "workflow_id inconnu (format chaîne brute)",
                    "value": {
                      "workflow_id": "Invalid workflow_id."
                    }
                  },
                  "Insufficient credits": {
                    "summary": "L'organisation n'a plus de crédits",
                    "value": {
                      "detail": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  },
                  "Blocklisted vendor_data": {
                    "summary": "vendor_data est sur liste de blocage",
                    "value": {
                      "vendor_data": "This user or business has been blocked and cannot create new verification sessions."
                    }
                  },
                  "Portrait image too large": {
                    "summary": "portrait_image ne passe pas la validation de la taille",
                    "value": {
                      "portrait_image": [
                        "Image size exceeds 2MB."
                      ]
                    }
                  },
                  "No stored face for vendor_data": {
                    "summary": "Workflow de Correspondance faciale sans portrait_image et sans visage enregistré pour l'utilisateur vendor_data",
                    "value": {
                      "portrait_image": "No stored face image was found for this user. Send a portrait_image, or complete an approved verification with face liveness or an ID document for this vendor_data first."
                    }
                  },
                  "Portrait image required without vendor_data": {
                    "summary": "Workflow de Correspondance faciale sans portrait_image et sans vendor_data",
                    "value": {
                      "portrait_image": "A portrait image is required to perform face match for this workflow. Send a portrait_image, or provide the vendor_data of a user with a previously stored face image to reuse it."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé incorrecte, révoquée ou expirée renvoie `401`. L'endpoint renvoie `403` lorsque l'en-tête `x-api-key` est manquant ou que la clé API est valide mais que le client n'a pas l'autorisation de créer des sessions dans cette application (par exemple, la clé API appartient à une autre organisation). Ces échecs partagent le corps `{\"detail\": \"You do not have permission to perform this action.\"}`. Vérifiez que l'en-tête `x-api-key` est présent et appartient à l'application visée, récupérez à nouveau la clé API de l'application via l'[API Auth](/fr/auth-api/get-credentials) si nécessaire, puis réessayez.\n\n**Application supprimée :** pendant quelques minutes après la suppression d'une application, une requête effectuée avec l'une de ses clés API peut répondre `{\"detail\": \"This application was deleted.\", \"code\": \"application_deleted\"}`. Ne réessayez pas : l'application et ses clés API n'existent plus. Après ces quelques minutes, la clé est refusée comme n'importe quelle autre clé non valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "You do not have permission to perform this action."
                    },
                    "code": {
                      "type": "string",
                      "description": "Raison lisible par machine, présente uniquement lors de certains échecs. `application_deleted` : la clé API appartient à une application qui a été supprimée.",
                      "example": "application_deleted"
                    }
                  },
                  "required": [
                    "detail"
                  ]
                },
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key` ou clé API non valide",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "No permission": {
                    "summary": "Le client ne peut pas créer de sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Application deleted": {
                    "summary": "Clé API d'une application supprimée",
                    "value": {
                      "detail": "This application was deleted.",
                      "code": "application_deleted"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée — plus de 600 requêtes de création de session dans une fenêtre de 60 secondes depuis la même clé API / IP. Examinez `Retry-After` et temporisez avant de réessayer.\n\n**Remarque :** Le code source définit également une limite `FREE_SESSION_RATE_LIMIT` de 10 appels/minute aux côtés de `PAID_SESSION_RATE_LIMIT=600` (`sessions/serializers/session.py`), mais ce plafond de l'offre gratuite n'est **pas appliqué à cet endpoint V3** — le middleware de limitation de débit applique la limite de 600/min `SESSION_CREATE_RATE_LIMIT` quel que soit le forfait. 600/min est la seule limite que vous pouvez atteindre ici.",
            "headers": {
              "Retry-After": {
                "description": "Nombre de secondes que l'appelant doit attendre avant de réessayer la requête.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 42
                }
              },
              "X-RateLimit-Limit": {
                "description": "Nombre maximal de requêtes autorisées dans la fenêtre actuelle de 60 secondes pour la limite qui a été dépassée (600 pour session-create). Absent sur la variante de quota sandbox.",
                "schema": {
                  "type": "integer",
                  "example": 600
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Nombre de requêtes encore autorisées dans la fenêtre actuelle pour la limite dépassée. Absent sur la variante de quota sandbox.",
                "schema": {
                  "type": "integer",
                  "minimum": 0,
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Secondes epoch UTC auxquelles la fenêtre actuelle de limite de débit est réinitialisée. Absent sur la variante de quota sandbox.",
                "schema": {
                  "type": "integer",
                  "minimum": 0,
                  "example": 1747497600
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Explication lisible par l'humain du dépassement de la limite de débit. Utilisez ce message pour identifier laquelle des trois limites a été atteinte.",
                      "example": "Session creation rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                },
                "examples": {
                  "Session-create limit": {
                    "summary": "Plus de 600 requêtes de création de session par minute",
                    "value": {
                      "detail": "Session creation rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  },
                  "Sandbox session quota": {
                    "summary": "L'application en sandbox a dépassé 500 sessions en 24 heures",
                    "value": {
                      "detail": "Sandbox session quota exceeded (500 sessions per 24h). Wait for the window to reset. Expected available in 3600 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/session/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"workflow_id\": \"11111111-2222-3333-4444-555555555555\",\n    \"vendor_data\": \"user-123\",\n    \"callback\": \"https://example.com/verification/callback\",\n    \"callback_method\": \"both\",\n    \"metadata\": {\"user_type\": \"premium\", \"account_id\": \"ABC123\"},\n    \"language\": \"en\",\n    \"contact_details\": {\n      \"email\": \"john.doe@example.com\",\n      \"send_notification_emails\": true,\n      \"email_lang\": \"en\",\n      \"phone\": \"+14155552671\"\n    },\n    \"expected_details\": {\n      \"first_name\": \"John\",\n      \"last_name\": \"Doe\",\n      \"date_of_birth\": \"1990-05-15\",\n      \"id_country\": \"USA\",\n      \"expected_document_types\": [\"P\", \"ID\"]\n    }\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.create(\n    workflow_id=\"11111111-2222-3333-4444-555555555555\",\n    vendor_data=\"user-123\",\n    callback=\"https://example.com/verification/callback\",\n    callback_method=\"both\",\n    metadata={\"user_type\": \"premium\", \"account_id\": \"ABC123\"},\n    language=\"en\",\n    contact_details={\n        \"email\": \"john.doe@example.com\",\n        \"send_notification_emails\": True,\n        \"email_lang\": \"en\",\n        \"phone\": \"+14155552671\",\n    },\n    expected_details={\n        \"first_name\": \"John\",\n        \"last_name\": \"Doe\",\n        \"date_of_birth\": \"1990-05-15\",\n        \"nationality\": \"USA\",\n        \"id_country\": \"USA\",\n        \"expected_document_types\": [\"P\", \"ID\"],\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.create({\n  workflow_id: \"11111111-2222-3333-4444-555555555555\",\n  vendor_data: \"user-123\",\n  callback: \"https://example.com/verification/callback\",\n  callback_method: \"both\",\n  metadata: { user_type: \"premium\", account_id: \"ABC123\" },\n  language: \"en\",\n  contact_details: {\n    email: \"john.doe@example.com\",\n    send_notification_emails: true,\n    email_lang: \"en\",\n    phone: \"+14155552671\",\n  },\n  expected_details: {\n    first_name: \"John\",\n    last_name: \"Doe\",\n    date_of_birth: \"1990-05-15\",\n    nationality: \"USA\",\n    id_country: \"USA\",\n    expected_document_types: [\"P\", \"ID\"],\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Create(ctx, didit.SessionsCreateParams{\n\tWorkflowID:     \"11111111-2222-3333-4444-555555555555\",\n\tVendorData:     didit.String(\"user-123\"),\n\tCallback:       didit.String(\"https://example.com/verification/callback\"),\n\tCallbackMethod: didit.Some(didit.SessionsCreateParamsCallbackMethod(\"both\")),\n\tMetadata:       didit.Some[any](map[string]any{\"user_type\": \"premium\", \"account_id\": \"ABC123\"}),\n\tLanguage:       didit.Some(didit.SessionsCreateParamsLanguage(\"en\")),\n\tContactDetails: didit.Some(didit.SessionsCreateParamsContactDetails{\n\t\tEmail:                  didit.String(\"john.doe@example.com\"),\n\t\tSendNotificationEmails: didit.Bool(true),\n\t\tEmailLang:              didit.Some(didit.SessionsCreateParamsContactDetailsEmailLang(\"en\")),\n\t\tPhone:                  didit.String(\"+14155552671\"),\n\t}),\n\tExpectedDetails: didit.Some(didit.SessionsCreateParamsExpectedDetails{\n\t\tFirstName:             didit.String(\"John\"),\n\t\tLastName:              didit.String(\"Doe\"),\n\t\tDateOfBirth:           didit.String(\"1990-05-15\"),\n\t\tNationality:           didit.String(\"USA\"),\n\t\tIDCountry:             didit.String(\"USA\"),\n\t\tExpectedDocumentTypes: didit.Some([]didit.SessionsCreateParamsExpectedDetailsExpectedDocumentTypes{\"P\", \"ID\"}),\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.LocalDate;\nimport java.util.List;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.SessionsCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().create(SessionsCreateParams.builder()\n        .workflowId(\"11111111-2222-3333-4444-555555555555\")\n        .vendorData(\"user-123\")\n        .callback(\"https://example.com/verification/callback\")\n        .callbackMethod(SessionsCreateParams.CallbackMethod.of(\"both\"))\n        .metadata(Map.of(\"user_type\", \"premium\", \"account_id\", \"ABC123\"))\n        .language(SessionsCreateParams.Language.of(\"en\"))\n        .contactDetails(SessionsCreateParams.ContactDetails.builder()\n                .email(\"john.doe@example.com\")\n                .sendNotificationEmails(true)\n                .emailLang(SessionsCreateParams.ContactDetails.EmailLang.of(\"en\"))\n                .phone(\"+14155552671\")\n                .build())\n        .expectedDetails(SessionsCreateParams.ExpectedDetails.builder()\n                .firstName(\"John\")\n                .lastName(\"Doe\")\n                .dateOfBirth(LocalDate.parse(\"1990-05-15\"))\n                .nationality(\"USA\")\n                .idCountry(\"USA\")\n                .expectedDocumentTypes(List.of(SessionsCreateParams.ExpectedDetails.ExpectedDocumentTypes.of(\"P\"), SessionsCreateParams.ExpectedDetails.ExpectedDocumentTypes.of(\"ID\")))\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->create([\n    'workflow_id' => '11111111-2222-3333-4444-555555555555',\n    'vendor_data' => 'user-123',\n    'callback' => 'https://example.com/verification/callback',\n    'callback_method' => 'both',\n    'metadata' => ['user_type' => 'premium', 'account_id' => 'ABC123'],\n    'language' => 'en',\n    'contact_details' => [\n        'email' => 'john.doe@example.com',\n        'send_notification_emails' => true,\n        'email_lang' => 'en',\n        'phone' => '+14155552671',\n    ],\n    'expected_details' => [\n        'first_name' => 'John',\n        'last_name' => 'Doe',\n        'date_of_birth' => '1990-05-15',\n        'nationality' => 'USA',\n        'id_country' => 'USA',\n        'expected_document_types' => ['P', 'ID'],\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.create(\n  workflow_id: \"11111111-2222-3333-4444-555555555555\",\n  vendor_data: \"user-123\",\n  callback: \"https://example.com/verification/callback\",\n  callback_method: \"both\",\n  metadata: { user_type: \"premium\", account_id: \"ABC123\" },\n  language: \"en\",\n  contact_details: {\n    email: \"john.doe@example.com\",\n    send_notification_emails: true,\n    email_lang: \"en\",\n    phone: \"+14155552671\",\n  },\n  expected_details: {\n    first_name: \"John\",\n    last_name: \"Doe\",\n    date_of_birth: \"1990-05-15\",\n    nationality: \"USA\",\n    id_country: \"USA\",\n    expected_document_types: [\"P\", \"ID\"],\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.CreateAsync(new SessionsCreateParams\n{\n    WorkflowId = \"11111111-2222-3333-4444-555555555555\",\n    VendorData = \"user-123\",\n    Callback = \"https://example.com/verification/callback\",\n    CallbackMethod = new SessionsCreateParamsCallbackMethod(\"both\"),\n    Metadata = new Dictionary<string, object> { [\"user_type\"] = \"premium\", [\"account_id\"] = \"ABC123\" },\n    Language = new SessionsCreateParamsLanguage(\"en\"),\n    ContactDetails = new SessionsCreateParamsContactDetails\n    {\n        Email = \"john.doe@example.com\",\n        SendNotificationEmails = true,\n        EmailLang = new SessionsCreateParamsContactDetailsEmailLang(\"en\"),\n        Phone = \"+14155552671\",\n    },\n    ExpectedDetails = new SessionsCreateParamsExpectedDetails\n    {\n        FirstName = \"John\",\n        LastName = \"Doe\",\n        DateOfBirth = \"1990-05-15\",\n        Nationality = \"USA\",\n        IdCountry = \"USA\",\n        ExpectedDocumentTypes = new SessionsCreateParamsExpectedDetailsExpectedDocumentTypes[] { \"P\", \"ID\" },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "workflow_id"
                ],
                "properties": {
                  "workflow_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Identifiant stable du workflow définissant les étapes de vérification que la session exécutera. Les workflows sont créés et gérés sur la page [Workflows](/fr/console/workflows) de la Console. Le paramètre `workflow_id` détermine également implicitement si la session relève du KYC ou du KYB.",
                    "example": "11111111-2222-3333-4444-555555555555",
                    "x-readme-id": "0.0"
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Un identifiant unique pour l'utilisateur en cours de vérification, tel qu'un UUID, une adresse e-mail ou un identifiant utilisateur interne. Ce champ sert à : (1) **Regroupement d'utilisateurs** — les sessions ayant le même vendor_data sont associées au même profil utilisateur dans l'onglet Utilisateurs. (2) **Détection de doublons entre sessions** — lors de la vérification de visages, documents, numéros de téléphone, e-mails, adresses IP ou empreintes d'appareils dupliqués, les sessions avec le même vendor_data sont traitées comme étant le même utilisateur et exclues des correspondances. Sans vendor_data, chaque session est traitée comme un utilisateur unique et tous les doublons potentiels sont signalés. Nous recommandons vivement de toujours fournir un vendor_data afin de réduire le bruit dans la détection des doublons.",
                    "example": "user-123",
                    "x-readme-id": "0.1"
                  },
                  "multi_account_segment": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Domaine optionnel de détection de doublons au sein de votre organisation. Les vérifications de visages en double comparent cette session uniquement avec d'autres sessions portant le même segment, afin que des bases de comptes distinctes (comptes personnels et professionnels, ou une par sous-client B2B) ne signalent pas une personne détenant légitimement un compte dans chacune. Omettez-le pour utiliser le domaine unique par défaut, qui est celui utilisé par chaque session actuellement. La mise en correspondance avec la liste de blocage et la liste d'autorisation ignore ce champ.",
                    "example": "business-accounts"
                  },
                  "callback": {
                    "type": "string",
                    "description": "URL vers laquelle rediriger l'utilisateur une fois la vérification terminée. Didit ajoute automatiquement `verificationSessionId` et `status` (Approved, Declined, In Review) en tant que paramètres de requête. Les schémas d'URL personnalisés (par exemple `myapp://`) sont pris en charge pour les rappels mobiles. En cas d'omission, le `callback_url` par défaut du workflow est utilisé. Lorsque l'application a des domaines autorisés (`allowed_domains` sur `PATCH /v3/webhook/`), un rappel `http` ou `https` doit appartenir à l'une de ces origines (le même schéma, le même hôte et le même port), sinon la requête échoue avec 400 sur `callback` : `callback must be on one of the application's allowed domains: https://app.example.com`. Les schémas d'URL personnalisés sont toujours acceptés.",
                    "example": "https://example.com/verification/callback",
                    "x-readme-id": "0.2"
                  },
                  "callback_method": {
                    "type": "string",
                    "description": "Détermine quel appareil doit gérer la redirection vers l'URL de rappel fournie. Utilisez `initiator` pour rediriger uniquement l'appareil qui a démarré le flux, `completer` pour l'appareil qui le termine, ou `both` pour autoriser l'un ou l'autre appareil à déclencher le rappel. Si vous constatez que le rappel ne se déclenche pas de manière fiable, nous vous recommandons de définir cette valeur sur `both`.",
                    "enum": [
                      "initiator",
                      "completer",
                      "both"
                    ],
                    "default": "initiator",
                    "example": "both",
                    "x-readme-id": "0.3"
                  },
                  "metadata": {
                    "description": "JSON arbitraire stocké avec la session et renvoyé dans la réponse et les webhooks. Toute valeur JSON est acceptée (objet, chaîne, nombre, tableau), mais un objet JSON de paires clé/valeur est recommandé. Non visible par l'utilisateur final. Utilisez-le pour transmettre vos propres identifiants de corrélation, variantes d'A/B testing ou contexte métier.",
                    "example": {
                      "user_type": "premium",
                      "account_id": "ABC123"
                    },
                    "x-readme-id": "0.4"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 50
                    },
                    "maxItems": 10,
                    "description": "Tags ajoutés à la session lors de sa création, par leur nom. Jusqu'à 10, de 50 caractères maximum chacun. Les noms sont insensibles à la casse et stockés en majuscules. Un nom qui n'existe pas encore dans l'application est créé en tant que nouveau tag. Les tags s'affichent sur la session dans la console, où vous pouvez filtrer selon ces derniers.",
                    "example": [
                      "VIP",
                      "ONBOARDING Q4"
                    ]
                  },
                  "language": {
                    "type": "string",
                    "description": "Code de langue (ISO 639-1) pour l'interface du processus de vérification. Contrôle la langue affichée à l'utilisateur final pendant la vérification. S'il n'est pas fourni, la langue du navigateur sera automatiquement détectée et utilisée. Consultez toutes les langues prises en charge [ici](/fr/integration/supported-languages).",
                    "enum": [
                      "en",
                      "ar",
                      "bg",
                      "bn",
                      "bs",
                      "ca",
                      "cnr",
                      "cs",
                      "da",
                      "de",
                      "el",
                      "es",
                      "et",
                      "fa",
                      "fi",
                      "fr",
                      "he",
                      "hi",
                      "hr",
                      "hu",
                      "hy",
                      "id",
                      "it",
                      "ja",
                      "ka",
                      "kk",
                      "ko",
                      "ky",
                      "lt",
                      "lv",
                      "mk",
                      "mn",
                      "ms",
                      "nl",
                      "no",
                      "pl",
                      "pt-BR",
                      "pt",
                      "ro",
                      "ru",
                      "sk",
                      "sl",
                      "so",
                      "sq",
                      "sr",
                      "sv",
                      "th",
                      "tr",
                      "uk",
                      "uz",
                      "vi",
                      "zh-CN",
                      "zh-TW",
                      "zh"
                    ],
                    "example": "en",
                    "x-readme-id": "0.5"
                  },
                  "contact_details": {
                    "type": "object",
                    "description": "Coordonnées de l'utilisateur pouvant être utilisées pour les notifications, le préremplissage des formulaires de vérification et la vérification du téléphone. Cela comprend l'adresse e-mail, la langue préférée pour les communications et le numéro de téléphone.",
                    "example": {
                      "email": "john.doe@example.com",
                      "send_notification_emails": true,
                      "email_lang": "en",
                      "phone": "+14155552671"
                    },
                    "properties": {
                      "email": {
                        "type": "string",
                        "format": "email",
                        "description": "Adresse e-mail de l'utilisateur (par exemple, « john.doe@example.com ») qui sera utilisée lors de l'étape de [Vérification de l'e-mail](/fr/core-technology/email-verification/overview). Si elle n'est pas fournie, l'utilisateur doit la renseigner pendant le flux de vérification.",
                        "example": "john.doe@example.com",
                        "x-readme-id": "1.0"
                      },
                      "send_notification_emails": {
                        "type": "boolean",
                        "default": false,
                        "description": "Si true et qu'un e-mail est fourni, Didit envoie l'e-mail initial « Vérifiez votre identité » de manière asynchrone lors de la création de la session de vérification des utilisateurs (KYC) ou de vérification d'entreprise (KYB). Didit envoie également les notifications de statut de vérification pour les sessions nécessitant un examen manuel à l'adresse e-mail fournie (par exemple, de « In Review » à « Approved » ou « Declined »). Cela aide les utilisateurs à revenir sur votre application une fois leur vérification terminée. Si la marque blanche est activée pour la session, l'e-mail envoyé sera en marque blanche.",
                        "example": true,
                        "x-readme-id": "1.1"
                      },
                      "email_lang": {
                        "type": "string",
                        "description": "Code de langue (ISO 639-1) pour les notifications par e-mail. Contrôle la langue de toutes les communications par e-mail (par exemple, \"en\", \"es\", \"fr\"). Aucune valeur par défaut n'est stockée — en cas d'omission, l'e-mail d'invitation à la vérification bascule simplement sur l'anglais (`en`) au moment de l'envoi. L'enum ci-dessous est un aperçu ; la source de référence en temps réel pour les valeurs acceptées est la documentation des [langues prises en charge](/fr/integration/supported-languages) — consultez-la systématiquement avant de vous fier à un code spécifique.",
                        "enum": [
                          "en",
                          "ar",
                          "bg",
                          "bn",
                          "bs",
                          "ca",
                          "cnr",
                          "cs",
                          "da",
                          "de",
                          "el",
                          "es",
                          "et",
                          "fa",
                          "fi",
                          "fr",
                          "he",
                          "hi",
                          "hr",
                          "hu",
                          "hy",
                          "id",
                          "it",
                          "ja",
                          "ka",
                          "kk",
                          "ko",
                          "ky",
                          "lt",
                          "lv",
                          "mk",
                          "mn",
                          "ms",
                          "nl",
                          "no",
                          "pl",
                          "pt-BR",
                          "pt",
                          "ro",
                          "ru",
                          "sk",
                          "sl",
                          "so",
                          "sq",
                          "sr",
                          "sv",
                          "th",
                          "tr",
                          "uk",
                          "uz",
                          "vi",
                          "zh-CN",
                          "zh-TW",
                          "zh"
                        ],
                        "example": "en",
                        "x-readme-id": "1.2"
                      },
                      "phone": {
                        "type": "string",
                        "description": "Numéro de téléphone au format E.164 (par ex. \"+14155552671\") qui sera utilisé lors de l'étape de [Vérification du téléphone](/fr/core-technology/phone-verification/overview). S'il n'est pas fourni, l'utilisateur doit le fournir pendant le flux de vérification. Ignoré pour les workflows de Vérification d'entreprise (KYB). **Important :** Ce numéro de téléphone n'est appliqué que s'il s'agit d'un numéro de téléphone E.164 valide. Si le numéro fourni est invalide ou ne peut pas être analysé, il sera ignoré et l'utilisateur pourra saisir n'importe quel numéro de téléphone valide lors de l'étape de vérification du téléphone.",
                        "example": "+14155552671",
                        "x-readme-id": "1.3"
                      }
                    },
                    "x-readme-id": "0.4"
                  },
                  "expected_details": {
                    "type": "object",
                    "description": "Informations attendues sur l'utilisateur utilisées pour la validation croisée avec les données extraites de sa pièce d'identité, du Justificatif de domicile et d'autres étapes de vérification. Les discordances apparaissent sous forme d'avertissements sur la décision ; certains champs (par ex. `id_country`, `expected_document_types`) modifient également le parcours côté utilisateur. Pour les workflows de Vérification d'entreprise (KYB), seuls les champs relatifs à l'entreprise (`company_name`, `registry_country`, `registration_number`) sont utilisés — ils préremplissent la recherche dans le registre des sociétés pour l'utilisateur — et tous les champs relatifs aux personnes physiques sont ignorés.",
                    "example": {
                      "first_name": "John",
                      "last_name": "Doe",
                      "date_of_birth": "1990-05-15",
                      "nationality": "USA",
                      "id_country": "USA",
                      "expected_document_types": [
                        "P",
                        "ID"
                      ]
                    },
                    "properties": {
                      "first_name": {
                        "type": "string",
                        "description": "Prénom de l'utilisateur. Par exemple, `John`. La correspondance utilise une comparaison approximative, et vous pouvez ajuster la rigueur en configurant le seuil de score de correspondance du nom dans la Console pour les workflows Justificatif d'identité et Justificatif de domicile.",
                        "example": "John",
                        "x-readme-id": "1.0"
                      },
                      "last_name": {
                        "type": "string",
                        "description": "Nom de famille de l'utilisateur. Par exemple, `Doe`. La correspondance utilise une comparaison approximative, et vous pouvez ajuster la rigueur en configurant le seuil de score de correspondance du nom dans la Console pour les workflows Justificatif d'identité et Justificatif de domicile.",
                        "example": "Doe",
                        "x-readme-id": "1.1"
                      },
                      "date_of_birth": {
                        "type": "string",
                        "format": "date",
                        "description": "Date de naissance de l'utilisateur au format : YYYY-MM-DD. Par exemple, `1990-05-15`.",
                        "example": "1990-05-15",
                        "x-readme-id": "1.2"
                      },
                      "gender": {
                        "type": "string",
                        "nullable": true,
                        "enum": [
                          "M",
                          "F"
                        ],
                        "default": null,
                        "description": "Genre de l'utilisateur. Doit être 'M', 'F' ou null.",
                        "example": "M",
                        "x-readme-id": "1.3"
                      },
                      "nationality": {
                        "type": "string",
                        "description": "Code pays ISO 3166-1 alpha-3 représentant le pays d'origine du candidat. Par exemple, `USA`. Voir la [liste complète des codes pays pris en charge](https://docs.didit.me/fr/core-technology/id-verification/supported-documents-id-verification#documents-pris-en-charge-par-pays).",
                        "example": "USA",
                        "x-readme-id": "1.4"
                      },
                      "country": {
                        "type": "string",
                        "description": "Code pays ISO 3166-1 alpha-3 utilisé comme solution de repli pour les vérifications de non-concordance de pays de la Vérification d'identité et du Justificatif de domicile. Requis lorsque `address` est fournie et que ni `id_country` ni `poa_country` ne sont définis.",
                        "example": "USA",
                        "x-readme-id": "1.4.1"
                      },
                      "id_country": {
                        "type": "string",
                        "description": "Code pays ISO 3166-1 alpha-3 représentant le pays attendu du document d'identité du candidat, qui peut différer de la nationalité. Par exemple, `GBR`. Prévaudra sur `country` pour les vérifications de non-concordance de pays de la vérification d'identité. Voir la [liste complète des codes pays pris en charge](https://docs.didit.me/fr/core-technology/id-verification/supported-documents-id-verification#documents-pris-en-charge-par-pays).",
                        "example": "GBR",
                        "x-readme-id": "1.5"
                      },
                      "poa_country": {
                        "type": "string",
                        "description": "Code pays ISO 3166-1 alpha-3 représentant le pays attendu du document de Justificatif de domicile. Par exemple, `USA`. Prévaudra sur `country` pour les vérifications de non-concordance de pays du justificatif de domicile. Voir la [liste complète des codes pays pris en charge](https://docs.didit.me/fr/core-technology/id-verification/supported-documents-id-verification#documents-pris-en-charge-par-pays).",
                        "example": "USA",
                        "x-readme-id": "1.5.1"
                      },
                      "address": {
                        "type": "string",
                        "description": "L'adresse dans un format lisible par un humain, comprenant autant d'informations que possible. Par exemple, `123 Main St, San Francisco, CA 94105, USA`. Lorsqu'elle est fournie, vous devez également transmettre `country` ou `poa_country`, sinon la requête échoue avec `400`.",
                        "example": "123 Main St, San Francisco, CA 94105, USA",
                        "x-readme-id": "1.6"
                      },
                      "identification_number": {
                        "type": "string",
                        "description": "Le numéro de document, le numéro personnel ou l'identifiant fiscal de l'utilisateur. Par exemple, `123456789`.",
                        "example": "123456789",
                        "x-readme-id": "1.7"
                      },
                      "ip_address": {
                        "type": "string",
                        "description": "Adresse IP attendue pour la session, au format IPv4 ou IPv6. Si l'adresse IP réelle diffère de cette valeur, un avertissement sera consigné. Par exemple, `192.168.1.100` ou `2001:db8::1`.",
                        "example": "192.168.1.100",
                        "x-readme-id": "1.8"
                      },
                      "expected_document_types": {
                        "type": "array",
                        "description": "Restreint les types de documents que l'utilisateur peut présenter lors de l'étape de vérification d'identité (OCR). Lorsqu'il est défini, l'écran de sélection de document affiche uniquement les types demandés et le `documents_allowed` renvoyé est filtré en conséquence. Les valeurs sont insensibles à la casse et dédupliquées ; les valeurs inconnues sont rejetées avec `400`. Codes autorisés : `P` (passeport), `ID` (carte d'identité nationale), `DL` (permis de conduire), `RP` (titre de séjour), `HIC` (carte d'assurance maladie), `TC` (carte fiscale), `SSC` (carte de sécurité sociale).",
                        "items": {
                          "type": "string",
                          "enum": [
                            "P",
                            "ID",
                            "DL",
                            "RP",
                            "HIC",
                            "TC",
                            "SSC"
                          ]
                        },
                        "example": [
                          "P",
                          "ID"
                        ],
                        "x-readme-id": "1.9"
                      },
                      "company_name": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Raison sociale attendue de l'entreprise en cours de vérification. Par exemple, `Tesco PLC`. Préremplit le champ du nom de l'entreprise lors de la recherche dans le registre pour les workflows de Vérification d'entreprise (KYB) ; lorsque `registration_number` est également fourni, la recherche dans le registre combine les deux identifiants. Ignoré pour les workflows KYC.",
                        "example": "Tesco PLC",
                        "x-readme-id": "1.10"
                      },
                      "registry_country": {
                        "type": "string",
                        "maxLength": 10,
                        "description": "Code ISO 3166-1 alpha-2 du pays dans le registre des sociétés duquel l'entreprise est enregistrée. Par exemple, `GB`. Lorsque les registres des sociétés fonctionnent au niveau de l'État ou de la province, ajoutez le code de subdivision ISO 3166-2 sous la forme `XX-YY` : `US-CA` cible le registre de Californie. Même format que `country_code` sur l'[API de recherche dans le registre KYB](https://docs.didit.me/fr/standalone-apis/kyb-registry-search). Présélectionne le pays du registre dans les workflows de vérification d'entreprise (KYB) ; ignoré pour les workflows KYC.",
                        "example": "US-CA",
                        "x-readme-id": "1.11"
                      },
                      "registration_number": {
                        "type": "string",
                        "maxLength": 100,
                        "description": "Numéro d'immatriculation attendu de l'entreprise dans le registre des sociétés. Par exemple, `00445790`. Préremplit le champ du numéro d'immatriculation lors de la recherche dans le registre pour les workflows de Vérification d'entreprise (KYB) ; lorsque `company_name` est également fourni, la recherche dans le registre combine les deux identifiants. Ignoré pour les workflows KYC.",
                        "example": "00445790",
                        "x-readme-id": "1.12"
                      }
                    },
                    "x-readme-id": "0.5"
                  },
                  "portrait_image": {
                    "type": "string",
                    "format": "byte",
                    "description": "Image portrait du visage de l'utilisateur final encodée en Base64 (max 2 Mo ; JPEG, PNG, WebP ou TIFF). Utilisée comme image de référence à comparer à la capture de détection du vivant lorsque le workflow est un workflow `Biometric Authentication` avec la Correspondance faciale activée, ou tout workflow en graphe où la Correspondance faciale s'exécute avant la vérification d'identité (OCR). Facultatif lorsque l'utilisateur identifié par `vendor_data` possède déjà une image de visage enregistrée : Didit la réutilise automatiquement, en appliquant l'ordre de priorité suivant : visage issu d'une détection du vivant approuvée, photo de puce d'ePassport, portrait de document d'identité, visage de profil enrôlé manuellement (seuls les visages issus de sessions approuvées ou les visages que vous avez vous-même enrôlés sont réutilisés). Lorsqu'elle est fournie, `portrait_image` prévaut toujours sur le visage enregistré. Si elle est omise et qu'aucun visage enregistré n'existe (ou que `vendor_data` n'est pas envoyé), la création de la session échoue avec une erreur `400`. Ignoré pour les autres types de workflow.",
                    "example": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=",
                    "x-readme-id": "0.6"
                  },
                  "sandbox_scenario": {
                    "type": "string",
                    "description": "Slug de scénario réservé à la sandbox. Uniquement accepté lorsque la clé API appartient à une application en mode sandbox ; rejeté sur les applications en production. Lorsqu'il est défini, le flux de création applique les valeurs magiques associées au scénario sur les champs d'entrée de la session (contact_details, expected_details) afin que les fournisseurs simulés reproduisent le résultat du scénario à travers le véritable pipeline de workflow. Consultez le catalogue de scénarios via GET /v1/sandbox/scenarios/ ou [Sandbox et données de test](/fr/integration/sandbox-testing). Vous pouvez également armer (ou réarmer) un scénario après la création via POST /v3/session/{sessionId}/sandbox/arm/, tant que la session est toujours à l'état `Not Started`. Pour la recherche sans document, utilisez `lookup_partial_match`, `lookup_no_match` ou `lookup_provider_error` afin de tester le budget de tentatives configuré et le mécanisme de secours. Pour les portefeuilles d'identité, utilisez `wallet_cancelled`, `wallet_timeout` ou `wallet_provider_error` ; `approve` simule un portefeuille vérifié. Tous les portefeuilles du catalogue peuvent être testés dans la sandbox, y compris les schémas non disponibles sur les applications en production. Les tentatives simulées ne sont pas facturées.",
                    "example": "decline_document_expired"
                  },
                  "sign": {
                    "type": "object",
                    "description": "Données d'entrée de Signature électronique pour cette session. `documents` correspond aux documents à signer, pour un workflow dont l'étape de Signature électronique extrait les documents de la session (`signature_documents_source` `session` ou `both`) : jusqu'à 20 documents et 50 Mo au total. `field_values` renseigne les champs dont le `prefill` est `api.<key>`, aussi bien sur les documents du workflow que de la session. Créer à nouveau une session pour les mêmes `workflow_id` et `vendor_data` renvoie la session en attente ; si cet appel transmet `sign`, ses documents, champs et valeurs doivent être identiques aux premiers, et toute différence renvoie `400` avec `{\"sign\": \"signature_document_changed\"}`. Voir [Documents de signature électronique](/fr/sessions-api/create-session#documents-de-signature-électronique).",
                    "properties": {
                      "documents": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 20,
                        "items": {
                          "$ref": "#/components/schemas/SessionSignDocument"
                        }
                      },
                      "field_values": {
                        "type": "object",
                        "description": "Valeurs indexées par la `<key>` de chaque source de préremplissage `api.<key>` : chaînes de 1 à 500 caractères pour les champs `text` et `data`, booléens pour une `checkbox`. `400` avec `field_value_unknown` pour une clé qu'aucun champ n'utilise, `field_value_missing` pour un champ obligatoire sans sa valeur, et `field_value_invalid` pour une valeur qui échoue à la validation de son champ.",
                        "additionalProperties": {
                          "oneOf": [
                            {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 500
                            },
                            {
                              "type": "boolean"
                            }
                          ]
                        },
                        "example": {
                          "credit_limit": "3,000 EUR"
                        }
                      }
                    }
                  },
                  "user_state": {
                    "type": "string",
                    "maxLength": 16,
                    "description": "Lieu de résidence de la personne, lorsqu'il est connu : un code de subdivision ISO 3166-2 (`US-IL`, `ES-M`) ou un code ou nom d'État américain (`IL`, `Illinois`). Un État dont la législation impose un consentement biométrique explicite (Illinois, Texas, Colorado) amène le flux de vérification à le demander avant de capturer un visage, avec le déclencheur `declared_state`. Une valeur non reconnue renvoie `400`. Voir [Consentement biométrique](/fr/getting-started/biometric-consent).",
                    "example": "US-IL"
                  },
                  "biometric_consent": {
                    "type": "object",
                    "description": "Consentement biométrique explicite que vous avez déjà recueilli auprès de la personne. Il satisfait à l'exigence, de sorte que le flux de vérification ne le redemande pas, et la décision l'enregistre avec `status: \"given\"` et le déclencheur `customer_collected`. Une réponse déjà donnée par la personne au cours du parcours n'est jamais remplacée. Voir [Consentement biométrique](/fr/getting-started/biometric-consent).",
                    "required": [
                      "given_at",
                      "text_version"
                    ],
                    "properties": {
                      "given_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Moment où la personne a donné son consentement biométrique explicite (ISO 8601). Ne peut pas être dans le futur."
                      },
                      "text_version": {
                        "type": "string",
                        "maxLength": 64,
                        "description": "Identifiant de version du texte de consentement que la personne a accepté, dans vos propres dossiers."
                      }
                    }
                  }
                },
                "example": {
                  "workflow_id": "11111111-2222-3333-4444-555555555555",
                  "vendor_data": "user-123",
                  "callback": "https://example.com/verification/callback",
                  "callback_method": "both",
                  "metadata": {
                    "user_type": "premium",
                    "account_id": "ABC123"
                  },
                  "language": "en",
                  "contact_details": {
                    "email": "john.doe@example.com",
                    "send_notification_emails": true,
                    "email_lang": "en",
                    "phone": "+14155552671"
                  },
                  "expected_details": {
                    "first_name": "John",
                    "last_name": "Doe",
                    "date_of_birth": "1990-05-15",
                    "id_country": "USA",
                    "expected_document_types": [
                      "P",
                      "ID"
                    ]
                  }
                }
              },
              "examples": {
                "Create KYC session": {
                  "summary": "Payload complet du scénario nominal pour une session de Vérification des utilisateurs (KYC)",
                  "description": "Appel de création réaliste utilisant chaque champ fréquemment configuré : sélection du workflow, liaison du fournisseur, routage de rappel, métadonnées, paramètres régionaux, pré-remplissage des contacts et informations attendues sur l'utilisateur. Copiez-collez ceci directement dans l'exemple cURL ci-dessus.",
                  "value": {
                    "workflow_id": "11111111-2222-3333-4444-555555555555",
                    "vendor_data": "user-123",
                    "callback": "https://example.com/verification/callback",
                    "callback_method": "both",
                    "metadata": {
                      "user_type": "premium",
                      "account_id": "ABC123"
                    },
                    "language": "en",
                    "contact_details": {
                      "email": "john.doe@example.com",
                      "send_notification_emails": true,
                      "email_lang": "en",
                      "phone": "+14155552671"
                    },
                    "expected_details": {
                      "first_name": "John",
                      "last_name": "Doe",
                      "date_of_birth": "1990-05-15",
                      "nationality": "USA",
                      "id_country": "USA",
                      "expected_document_types": [
                        "P",
                        "ID"
                      ]
                    }
                  }
                },
                "Create KYB session": {
                  "summary": "Payload de cas nominal pour une session de Vérification d'entreprise (KYB)",
                  "description": "Même format que l'appel KYC — c'est le `workflow_id` qui fait de la session une session KYB. `vendor_data` fait généralement référence à l'entreprise dans votre système et `contact_details.email` cible le représentant légal qui effectuera le flux. `expected_details` accepte les champs relatifs à l'entreprise (`company_name`, `registry_country`, `registration_number`), qui préremplissent la recherche dans le registre des sociétés ; les champs au niveau de la personne et `contact_details.phone` sont ignorés pour les workflows KYB.",
                  "value": {
                    "workflow_id": "33333333-4444-5555-6666-777777777777",
                    "vendor_data": "company-acme-001",
                    "callback": "https://example.com/kyb/callback",
                    "callback_method": "both",
                    "metadata": {
                      "tier": "enterprise",
                      "company_id": "ACME-001"
                    },
                    "expected_details": {
                      "company_name": "Tesco PLC",
                      "registry_country": "GB",
                      "registration_number": "00445790"
                    },
                    "language": "en",
                    "contact_details": {
                      "email": "legal-rep@acme.example.com",
                      "send_notification_emails": true,
                      "email_lang": "en"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/session/imports/": {
      "post": {
        "summary": "Créer une tâche d'importation de vérification",
        "description": "Créer une tâche d'importation asynchrone pour les sessions historiques de Vérification des utilisateurs, les sessions de Vérification d'entreprise (KYB), les enregistrements de surveillance des transactions ou les règles de statut personnalisé de workflow. Définissez `source=provider` pour migrer depuis un autre prestataire : Didit lit Sumsub, Onfido, Persona et ComplyCube avec votre clé en lecture seule, lit les enregistrements Veriff, iDenfy et MetaMap selon les identifiants que vous téléversez dans `file`, et importe un fichier d'exportation au format de Didit pour les autres prestataires. Les identifiants d'enregistrement sont préfixés par prestataire (`sumsub:<id>`) afin qu'une réexécution ignore tout ce qui se trouve déjà dans Didit, et un enregistrement importé via un fichier avec l'identifiant brut du prestataire est également reconnu, dans les deux sens, de sorte que passer d'une importation par fichier à une migration de prestataire n'importe jamais un enregistrement deux fois. Une application peut exécuter jusqu'à 4 tâches d'importation simultanément ; une tâche interrompue par un déploiement ou un redémarrage de worker reprend d'elle-même à partir de sa dernière ligne importée. Les importations sont désactivées par défaut et doivent être activées par organisation par Didit.",
        "operationId": "post_v3_session_imports_create",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "import_type": {
                    "type": "string",
                    "enum": [
                      "user_verification",
                      "business_verification",
                      "status_rules",
                      "transactions"
                    ],
                    "default": "user_verification",
                    "description": "Ce qu'il faut importer : sessions historiques de vérification des utilisateurs, sessions historiques de vérification d'entreprise, règles de statut personnalisées de workflow ou enregistrements historiques de surveillance des transactions."
                  },
                  "workflow_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID du workflow auquel les sessions importées ou les règles de statut doivent être rattachées. Requis pour user_verification, business_verification et status_rules. À omettre pour les transactions."
                  },
                  "source_format": {
                    "type": "string",
                    "enum": [
                      "csv",
                      "ndjson"
                    ],
                    "description": "Optionnel. Déduit de l'extension du fichier téléversé lorsqu'il est omis."
                  },
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Fichier CSV ou NDJSON canonique. Utilisez NDJSON pour les importations volumineuses. Taille maximale de téléversement : 25 Mo (utilisez `source_file_url` pour les fichiers plus volumineux). Mutuellement exclusif avec `source_file_url`."
                  },
                  "source_file_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Alternative au téléversement de fichier. Doit être une URL HTTPS résolvant vers une adresse publique (les réseaux privés/de bouclage sont rejetés). Mutuellement exclusif avec `file`."
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "file",
                      "provider"
                    ],
                    "description": "`provider` définit ceci comme une migration depuis un autre fournisseur de vérification d'identité. Omettez pour une importation de fichiers."
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "sumsub",
                      "jumio",
                      "veriff",
                      "onfido",
                      "persona",
                      "metamap",
                      "socure",
                      "idnow",
                      "shufti",
                      "idenfy",
                      "ondato",
                      "trulioo",
                      "au10tix",
                      "complycube",
                      "other"
                    ],
                    "description": "Source de migration, obtenue via `GET /v3/session/imports/providers/`. Requis lorsque `source` vaut `provider`."
                  },
                  "credentials": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "La clé en lecture seule du fournisseur, contenant les noms de champs listés par `credential_fields`. Chiffrée au repos, jamais renvoyée et effacée à la fin de l'importation. Envoyez-la sous forme de chaîne JSON dans du multipart."
                  },
                  "options": {
                    "type": "object",
                    "properties": {
                      "region": {
                        "type": "string",
                        "description": "La région du fournisseur, l'une de ses `regions` (Onfido : `eu`, `us`, `ca`)."
                      }
                    }
                  },
                  "status_mapping": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string",
                      "enum": [
                        "Approved",
                        "Declined",
                        "In Review",
                        "Expired",
                        "Not Finished",
                        "Abandoned"
                      ]
                    },
                    "description": "Modifications du mappage de statuts par défaut du fournisseur : statut source vers statut Didit. `Not Finished` et `Abandoned` sont ignorés et comptabilisés, jamais importés."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "default": false,
                    "description": "Compter ce que la migration importerait (par statut, déjà dans Didit, même personne, non terminé) sans rien écrire. La tâche se termine avec le statut `READY` ; démarrez-la avec `POST /v3/session/imports/{importId}/start/`."
                  },
                  "face_templates": {
                    "type": "boolean",
                    "default": false,
                    "description": "Générez des gabarits biométriques à partir des selfies importés et recherchez-les parmi les visages et la liste de blocage de l'application. Les correspondances sont signalées uniquement pour examen. Nécessite `lawful_basis_confirmed`."
                  },
                  "lawful_basis_confirmed": {
                    "type": "boolean",
                    "default": false,
                    "description": "Confirme que vous disposez d'une base légale pour partager ces selfies avec Didit en tant que sous-traitant."
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "source_file_url"
                ],
                "properties": {
                  "import_type": {
                    "type": "string",
                    "enum": [
                      "user_verification",
                      "business_verification",
                      "status_rules",
                      "transactions"
                    ],
                    "default": "user_verification",
                    "description": "Ce qu'il faut importer : sessions historiques de vérification des utilisateurs, sessions historiques de vérification d'entreprise, règles de statut personnalisées de workflow ou enregistrements historiques de surveillance des transactions."
                  },
                  "workflow_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID du workflow auquel les sessions importées ou les règles de statut doivent être rattachées. Requis pour user_verification, business_verification et status_rules. À omettre pour les transactions."
                  },
                  "source_format": {
                    "type": "string",
                    "enum": [
                      "csv",
                      "ndjson"
                    ],
                    "description": "Optionnel. Déduit de l'extension de fichier de l'URL lorsqu'il est omis."
                  },
                  "source_file_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Alternative au téléversement de fichier. Doit être une URL HTTPS résolvant vers une adresse publique (les réseaux privés/de bouclage sont rejetés). Mutuellement exclusif avec `file`."
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "file",
                      "provider"
                    ],
                    "description": "`provider` définit ceci comme une migration depuis un autre fournisseur de vérification d'identité. Omettez pour une importation de fichiers."
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "sumsub",
                      "jumio",
                      "veriff",
                      "onfido",
                      "persona",
                      "metamap",
                      "socure",
                      "idnow",
                      "shufti",
                      "idenfy",
                      "ondato",
                      "trulioo",
                      "au10tix",
                      "complycube",
                      "other"
                    ],
                    "description": "Source de migration, obtenue via `GET /v3/session/imports/providers/`. Requis lorsque `source` vaut `provider`."
                  },
                  "credentials": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "La clé en lecture seule du fournisseur, contenant les noms de champs listés par `credential_fields`. Chiffrée au repos, jamais renvoyée et effacée à la fin de l'importation. Envoyez-la sous forme de chaîne JSON dans du multipart."
                  },
                  "options": {
                    "type": "object",
                    "properties": {
                      "region": {
                        "type": "string",
                        "description": "La région du fournisseur, l'une de ses `regions` (Onfido : `eu`, `us`, `ca`)."
                      }
                    }
                  },
                  "status_mapping": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string",
                      "enum": [
                        "Approved",
                        "Declined",
                        "In Review",
                        "Expired",
                        "Not Finished",
                        "Abandoned"
                      ]
                    },
                    "description": "Modifications du mappage de statuts par défaut du fournisseur : statut source vers statut Didit. `Not Finished` et `Abandoned` sont ignorés et comptabilisés, jamais importés."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "default": false,
                    "description": "Compter ce que la migration importerait (par statut, déjà dans Didit, même personne, non terminé) sans rien écrire. La tâche se termine avec le statut `READY` ; démarrez-la avec `POST /v3/session/imports/{importId}/start/`."
                  },
                  "face_templates": {
                    "type": "boolean",
                    "default": false,
                    "description": "Générez des gabarits biométriques à partir des selfies importés et recherchez-les parmi les visages et la liste de blocage de l'application. Les correspondances sont signalées uniquement pour examen. Nécessite `lawful_basis_confirmed`."
                  },
                  "lawful_basis_confirmed": {
                    "type": "boolean",
                    "default": false,
                    "description": "Confirme que vous disposez d'une base légale pour partager ces selfies avec Didit en tant que sous-traitant."
                  }
                }
              },
              "examples": {
                "URL-based import": {
                  "value": {
                    "import_type": "user_verification",
                    "workflow_id": "9f9b1234-aaaa-bbbb-cccc-1234567890ab",
                    "source_file_url": "https://files.example.com/exports/sessions.ndjson"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tâche d'importation acceptée. Interrogez l'`uuid` renvoyé jusqu'à ce que le `status` soit `COMPLETED` ou `FAILED`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionImportJob"
                },
                "examples": {
                  "Job accepted": {
                    "value": {
                      "uuid": "3f9c1a2b-4d5e-4f60-8a7b-9c0d1e2f3a4b",
                      "status": "PENDING",
                      "import_type": "user_verification",
                      "source_format": "ndjson",
                      "source_filename": "sessions.ndjson",
                      "total_rows": 0,
                      "processed_rows": 0,
                      "checkpoint_row": 0,
                      "created_count": 0,
                      "updated_count": 0,
                      "skipped_count": 0,
                      "failed_count": 0,
                      "total_media_bytes": 0,
                      "last_error": null,
                      "created_at": "2026-05-17T08:42:11Z",
                      "updated_at": "2026-05-17T08:42:11Z",
                      "started_at": null,
                      "completed_at": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Workflow, type de fichier, taille de fichier, URL source ou combinaison de sélecteurs non valide. Une migration dont le fournisseur refuse la clé renvoie `code` (`invalid_credentials`, `missing_permission`, `wrong_region`, `provider_unavailable`, `rate_limited`, `ids_required`, `record_not_found`), `missing_permissions` et `suggested_region`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid workflow": {
                    "value": {
                      "workflow_id": [
                        "Invalid workflow_id."
                      ]
                    }
                  },
                  "Workflow required": {
                    "value": {
                      "workflow_id": [
                        "This field is required for this import type."
                      ]
                    }
                  },
                  "Wrong file type": {
                    "value": {
                      "file": [
                        "Only CSV and NDJSON files are supported."
                      ]
                    }
                  },
                  "File too large": {
                    "value": {
                      "file": [
                        "Import file exceeds the maximum allowed size."
                      ]
                    }
                  },
                  "No source": {
                    "value": {
                      "file": [
                        "Upload a file or provide source_file_url."
                      ]
                    }
                  },
                  "Both sources": {
                    "value": {
                      "file": [
                        "Use either file or source_file_url, not both."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Importations non activées, application sandbox ou clé API manquante (une clé erronée, révoquée ou expirée renvoie `401`). Les importations de vérifications sont désactivées par défaut et doivent être activées par Didit pour chaque organisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Imports not enabled": {
                    "value": {
                      "detail": "Verification imports are not enabled for this organization."
                    }
                  },
                  "Sandbox": {
                    "value": {
                      "detail": "Verification imports are not enabled for sandbox applications."
                    }
                  },
                  "Bad API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "L'application possède déjà 4 tâches d'importation actives (PENDING/PROCESSING/PAUSED), soit le nombre maximal qu'elle peut exécuter simultanément. Attendez que l'une d'elles se termine avant d'en démarrer une autre.",
            "content": {
              "application/json": {
                "examples": {
                  "Active job": {
                    "value": {
                      "detail": "This application already has 4 active import jobs, the most it can run at once. Wait for one to finish before starting another."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.create(\n    import_type=\"user_verification\",\n    workflow_id=\"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n    source_file_url=\"https://files.example.com/exports/sessions.ndjson\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.create({\n  import_type: \"user_verification\",\n  workflow_id: \"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n  source_file_url: \"https://files.example.com/exports/sessions.ndjson\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.Create(ctx, didit.SessionsImportsCreateParams{\n\tImportType:    didit.Some(didit.SessionsImportsCreateParamsImportType(\"user_verification\")),\n\tWorkflowID:    didit.String(\"9f9b1234-aaaa-bbbb-cccc-1234567890ab\"),\n\tSourceFileURL: didit.String(\"https://files.example.com/exports/sessions.ndjson\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsImportsCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().create(SessionsImportsCreateParams.builder()\n        .importType(SessionsImportsCreateParams.ImportType.of(\"user_verification\"))\n        .workflowId(\"9f9b1234-aaaa-bbbb-cccc-1234567890ab\")\n        .sourceFileUrl(\"https://files.example.com/exports/sessions.ndjson\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->create([\n    'import_type' => 'user_verification',\n    'workflow_id' => '9f9b1234-aaaa-bbbb-cccc-1234567890ab',\n    'source_file_url' => 'https://files.example.com/exports/sessions.ndjson',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.create(\n  import_type: \"user_verification\",\n  workflow_id: \"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n  source_file_url: \"https://files.example.com/exports/sessions.ndjson\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.CreateAsync(new SessionsImportsCreateParams\n{\n    ImportType = new SessionsImportsCreateParamsImportType(\"user_verification\"),\n    WorkflowId = \"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n    SourceFileUrl = \"https://files.example.com/exports/sessions.ndjson\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/imports/template/": {
      "get": {
        "summary": "Télécharger le modèle d'importation de vérifications",
        "description": "Télécharger l'en-tête CSV canonique pour les imports de vérifications. L'ensemble des colonnes est déterminé par `import_type`. La première colonne des modèles de session est la clé d'idempotence `external_id`.",
        "operationId": "get_v3_session_imports_template",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "retrieve_template",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "import_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "user_verification",
                "business_verification",
                "status_rules",
                "transactions"
              ],
              "default": "user_verification"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fichier modèle CSV.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas télécharger de modèles d'importation. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "summary": "Clé API manquante, invalide ou révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.sessions.imports.retrieve_template()\nwith open(\"download.csv\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.sessions.imports.retrieveTemplate();\nawait writeFile(\"download.csv\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.Sessions.Imports.RetrieveTemplate(ctx, didit.SessionsImportsRetrieveTemplateParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.csv\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.sessions().imports().retrieveTemplate()\n        .writeTo(Path.of(\"download.csv\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->sessions->imports->retrieveTemplate();\n$content->saveTo('download.csv');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.sessions.imports.retrieve_template\nFile.binwrite(\"download.csv\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.Sessions.Imports.RetrieveTemplateAsync();\nawait content.SaveToAsync(\"download.csv\");"
          }
        ]
      }
    },
    "/v3/session/imports/{importId}/": {
      "get": {
        "summary": "Récupérer un travail d'importation de vérifications",
        "description": "Récupérer les compteurs de progression de l'importation et le statut final pour un travail donné. Interrogez jusqu'à ce que `status` soit `COMPLETED` ou `FAILED` ; un `failed_count` > 0 signifie que certaines lignes ont été rejetées — listez-les via l'endpoint des erreurs.",
        "operationId": "get_v3_session_imports_retrieve",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Statut de la tâche d'importation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionImportJob"
                }
              }
            }
          },
          "404": {
            "description": "Tâche d'importation introuvable pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas lire les tâches d'importation pour cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "summary": "Clé API manquante, invalide ou révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/imports/{importId}/errors/": {
      "get": {
        "summary": "Lister les erreurs des lignes d'une importation de vérifications",
        "description": "Lister les erreurs au niveau des lignes pour une tâche d'importation de vérification, triées par `row_number`. Utilisez cet endpoint pour générer un fichier de nouvelle tentative corrigé contenant uniquement les lignes en échec.",
        "operationId": "get_v3_session_imports_errors",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "list_errors",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            },
            "description": "Taille de page. Vaut 50 par défaut si omis."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Décalage de départ (base zéro) du premier enregistrement à retourner."
          }
        ],
        "responses": {
          "200": {
            "description": "Erreurs de ligne paginées.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de lignes d'erreur — exact jusqu'à 100, plafonné à 100 au-delà. Fiez-vous au fait que `next` soit `null` pour détecter la dernière page."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SessionImportError"
                      }
                    }
                  }
                },
                "examples": {
                  "Row errors": {
                    "value": {
                      "count": 1,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                          "row_number": 17,
                          "external_id": "ext-000017",
                          "error": "status: invalid value 'unknown_status'",
                          "raw_row": {
                            "external_id": "ext-000017",
                            "status": "unknown_status",
                            "first_name": "Jane"
                          },
                          "created_at": "2026-05-17T08:44:02Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Tâche d'importation introuvable pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas lire les tâches d'importation pour cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "summary": "Clé API manquante, invalide ou révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.sessions.imports.list_errors(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.sessions.imports.listErrors(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Sessions.Imports.ListErrorsAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsImportsListErrorsParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.sessions().imports().listErrors(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->sessions->imports->listErrors('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.sessions.imports.list_errors(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Sessions.Imports.ListErrorsAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/decision/": {
      "get": {
        "summary": "Récupérer la décision complète d'une session de vérification",
        "description": "Récupérez le rapport de décision complet pour une session de vérification — le `status` consolidé de la session ainsi qu'un rapport par fonctionnalité de vérification exécutée par le workflow. Il s'agit de l'endpoint de lecture canonique pour les sessions de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) : le même chemin dessert les deux, et le discriminateur de premier niveau `session_kind` vous indique le format reçu (`\"user\"` ou `\"business\"`).\n\n**Chaque rapport de fonctionnalité est un tableau au pluriel.** Les workflows V3 sont des graphes pouvant exécuter la même fonctionnalité plusieurs fois, de sorte que chaque bloc (`id_verifications`, `nfc_verifications`, `liveness_checks`, `face_matches`, `poa_verifications`, `document_ai_documents`, `phone_verifications`, `email_verifications`, `aml_screenings`, `ip_analyses`, `database_validations`, `questionnaire_responses`) est un tableau JSON dont chaque élément comporte un `node_id` identifiant le nœud du graphe de workflow qui l'a produit. Lisez le NFC via `response.nfc_verifications[0]` — jamais sous un champ au singulier `nfc`. Un bloc est à `null` tant que le workflow n'a pas exécuté cette fonctionnalité au moins une fois ; les fonctionnalités non incluses dans le workflow n'apparaissent jamais avec des données. Les résultats de Signature électronique se trouvent dans `signatures`, qui n'est présent que si le workflow comporte une étape de Signature électronique.\n\n**Quand appeler cet endpoint.** Le modèle recommandé est piloté par les événements : attendez le webhook `status.updated` émis lorsque la session parvient à une décision (`Approved`, `Declined`, `In Review`), puis appelez cet endpoint une seule fois pour récupérer le rapport complet. Le sondage fonctionne également — l'endpoint peut être appelé à tout moment du cycle de vie de la session et renvoie les données produites jusqu'alors — mais l'approche webhook puis récupération est plus économique et plus rapide. Les URL des médias dans la réponse (images de documents, vidéos, PDF) sont des liens pré-signés à courte durée de vie : récupérez-les rapidement ou renouvelez la requête de décision pour en obtenir de nouvelles, et ne les conservez pas comme références à long terme.\n\n**Statuts.** Le `status` de premier niveau correspond au statut du cycle de vie de la session (`Not Started`, `In Progress`, `Awaiting User`, `In Review`, `Approved`, `Declined`, `Resubmitted`, `Expired`, `Kyc Expired`, `Abandoned`). Chaque élément de fonctionnalité comporte également son propre `status` de fonctionnalité (`Not Finished`, `Approved`, `Declined`, `In Review`, ...). Une session peut être `Approved` dans son ensemble alors qu'une fonctionnalité individuelle est `In Review`, selon les règles de décision du workflow.\n\n**Authentification et visibilité.** Authentifiez-vous avec la clé API de l'application dans l'en-tête `x-api-key` (un token Bearer d'utilisateur de la console doté de l'autorisation `read:sessions` fonctionne également). Seules les sessions appartenant à l'application authentifiée sont visibles. Si votre workflow restreint les attributs de la réponse, les champs non autorisés dans les éléments de fonctionnalité sont renvoyés à `null`, tandis que `status`, `warnings` et `node_id` sont toujours conservés.\n\n**Limites de débit.** Les requêtes GET sont limitées à 600 par minute par clé API. Tout dépassement de cette limite renvoie une réponse `429` accompagnée des en-têtes `Retry-After` et `X-RateLimit-*`.",
        "operationId": "get_v3_session_decision",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "retrieve_decision",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "responses": {
          "200": {
            "description": "Rapport de décision complet. `session_kind` distingue les deux structures : les sessions `user` contiennent les tableaux de fonctionnalités KYC présentés ci-dessous ; les sessions `business` contiennent quant à elles `registry_checks`, `document_verifications` et `key_people_checks` aux côtés des tableaux partagés. Les tableaux de fonctionnalités sont `null` tant que le workflow n'a pas exécuté cette fonctionnalité ; les URL de médias sont des liens présignés à courte durée de validité.",
            "content": {
              "application/json": {
                "examples": {
                  "Example": {
                    "summary": "Exemple complet",
                    "value": {
                      "session_id": "11111111-2222-3333-4444-555555555555",
                      "session_kind": "user",
                      "session_number": 43762,
                      "session_url": "https://verify.didit.me/session/11111111-2222-3333-4444-555555555555",
                      "status": "In Review",
                      "environment": "live",
                      "workflow_id": "11111111-2222-3333-4444-555555555555",
                      "features": [
                        "ID_VERIFICATION",
                        "NFC",
                        "LIVENESS",
                        "FACE_MATCH",
                        "POA",
                        "PHONE",
                        "DATABASE_VALIDATION",
                        "AML",
                        "IP_ANALYSIS"
                      ],
                      "vendor_data": "11111111-1111-1111-1111-111111111111",
                      "metadata": {
                        "user_type": "premium",
                        "account_id": "ABC123"
                      },
                      "expected_details": {
                        "first_name": "Carmen",
                        "last_name": "Española Española"
                      },
                      "contact_details": {
                        "email": "carmen@example.com",
                        "email_lang": "es",
                        "send_notification_emails": false,
                        "phone": null
                      },
                      "callback": "https://verify.didit.me/",
                      "id_verifications": [
                        {
                          "node_id": "feature_ocr_1",
                          "status": "Approved",
                          "document_type": "Identity Card",
                          "document_subtype": "ID_CARD_GENERIC",
                          "document_number": "CAA000000",
                          "personal_number": "99999999R",
                          "portrait_image": "https://<media-host>/portrait.jpg",
                          "front_image": "https://<media-host>/front.jpg",
                          "front_video": "https://<media-host>/front.mp4",
                          "back_image": "https://<media-host>/back.jpg",
                          "back_video": "https://<media-host>/back.mp4",
                          "full_front_image": "https://<media-host>/full_front.jpg",
                          "full_back_image": "https://<media-host>/full_back.jpg",
                          "front_image_camera_front": "https://<media-host>/front_camera_front.jpg",
                          "back_image_camera_front": "https://<media-host>/back_camera_front.jpg",
                          "date_of_birth": "1980-01-01",
                          "age": 45,
                          "expiration_date": "2031-06-02",
                          "date_of_issue": "2021-06-02",
                          "issuing_state": "ESP",
                          "issuing_state_name": "Spain",
                          "first_name": "Carmen",
                          "last_name": "Española Española",
                          "full_name": "Carmen Española Española",
                          "gender": "F",
                          "address": "Avda de Madrid 34, Madrid, Madrid",
                          "formatted_address": "Avda de Madrid 34, Madrid, Madrid 28822, Spain",
                          "place_of_birth": "Madrid",
                          "marital_status": "Single",
                          "nationality": "ESP",
                          "extra_fields": {
                            "dl_categories": [],
                            "blood_group": null
                          },
                          "mrz": {
                            "surname": "ESPANOLA ESPANOLA",
                            "name": "CARMEN",
                            "country": "ESP",
                            "nationality": "ESP",
                            "birth_date": "800101",
                            "expiry_date": "310602",
                            "sex": "F",
                            "document_type": "ID",
                            "document_number": "CAA000000",
                            "optional_data": "99999999R",
                            "optional_data_2": "",
                            "birth_date_hash": "4",
                            "expiry_date_hash": "8",
                            "document_number_hash": "4",
                            "final_hash": "1",
                            "personal_number": "99999999R",
                            "warnings": [],
                            "errors": [],
                            "mrz_type": "TD1",
                            "mrz_string": "IDESPCAA000000499999999R<<<<<<\n8001014F3106028ESP<<<<<<<<<<<1\nESPANOLA<ESPANOLA<<CARMEN<<<<<",
                            "mrz_key": "CAA000000480010143106028"
                          },
                          "parsed_address": {
                            "city": "Madrid",
                            "label": "Spain ID Card Address",
                            "region": "Madrid",
                            "country": "ES",
                            "category": "Residential",
                            "street_1": "Avda de Madrid 34",
                            "street_2": null,
                            "is_verified": true,
                            "postal_code": "28822",
                            "raw_results": {
                              "types": [
                                "street_address"
                              ],
                              "geometry": {
                                "location": {
                                  "lat": 37.4222804,
                                  "lng": -122.0843428
                                },
                                "viewport": {
                                  "northeast": {
                                    "lat": 37.4237349802915,
                                    "lng": -122.083183169709
                                  },
                                  "southwest": {
                                    "lat": 37.4210370197085,
                                    "lng": -122.085881130292
                                  }
                                },
                                "location_type": "ROOFTOP"
                              },
                              "place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
                              "formatted_address": "Avda de Madrid 34, 28822 Madrid, Spain",
                              "navigation_points": [
                                {
                                  "location": {
                                    "latitude": 37.4222804,
                                    "longitude": -122.0843428
                                  }
                                }
                              ],
                              "address_components": [
                                {
                                  "types": [
                                    "street_number"
                                  ],
                                  "long_name": "34",
                                  "short_name": "34"
                                },
                                {
                                  "types": [
                                    "route"
                                  ],
                                  "long_name": "Avda de Madrid",
                                  "short_name": "Avda de Madrid"
                                },
                                {
                                  "types": [
                                    "locality",
                                    "political"
                                  ],
                                  "long_name": "Madrid",
                                  "short_name": "Madrid"
                                },
                                {
                                  "types": [
                                    "country",
                                    "political"
                                  ],
                                  "long_name": "Spain",
                                  "short_name": "ES"
                                },
                                {
                                  "types": [
                                    "postal_code"
                                  ],
                                  "long_name": "28822",
                                  "short_name": "28822"
                                }
                              ]
                            },
                            "address_type": "Avda",
                            "document_location": {
                              "latitude": 37.4222804,
                              "longitude": -122.0843428
                            },
                            "formatted_address": "Avda de Madrid 34, 28822 Madrid, Spain"
                          },
                          "front_image_camera_front_face_match_score": 95.5,
                          "back_image_camera_front_face_match_score": 93.2,
                          "document_selfie_face_matches": [
                            {
                              "session_id": "3f0c9a52-7b1e-4d68-a2c4-5e9d8b7f1a20",
                              "session_number": 1180,
                              "similarity_percentage": 97.4,
                              "vendor_data": "user_ref_001",
                              "vendor_user_id": null,
                              "biometric_template_id": null,
                              "verification_date": "2026-09-02T09:15:00Z",
                              "user_details": {
                                "full_name": "Jane Doe"
                              },
                              "match_image_url": "https://<media-host>/match_face.jpg",
                              "status": "Approved",
                              "is_blocklisted": false,
                              "is_allowlisted": false,
                              "api_service": null,
                              "source": "session"
                            }
                          ],
                          "front_image_quality_score": {
                            "focus_score": 85.3,
                            "brightness_score": 92.1,
                            "brightness_issue": "ok",
                            "is_document_fully_visible": true,
                            "resolution_score": 72.4,
                            "overall_score": 88.7
                          },
                          "back_image_quality_score": {
                            "focus_score": 79.1,
                            "brightness_score": 90.5,
                            "brightness_issue": "ok",
                            "is_document_fully_visible": true,
                            "resolution_score": 72.4,
                            "overall_score": 85.2
                          },
                          "extra_files": [
                            "https://<media-host>/extra_id_verification.jpg"
                          ],
                          "matches": [
                            {
                              "session_id": "7d4f1f60-9c2e-4b8a-8f3d-2a1b5c6d7e8f",
                              "session_number": 1234,
                              "vendor_data": "user_ref_001",
                              "verification_date": "2024-06-15T10:30:00Z",
                              "user_details": {
                                "name": "John Smith",
                                "document_type": "ID",
                                "document_number": "CLM148418"
                              },
                              "status": "Approved",
                              "is_blocklisted": false,
                              "api_service": null,
                              "front_image_url": "https://<media-host>/document_front.jpg"
                            },
                            {
                              "session_id": "b2c8e4d1-6a3f-4e7b-95c0-1d8f2a6b4c9e",
                              "session_number": 1235,
                              "vendor_data": null,
                              "verification_date": "2024-05-20T14:45:00Z",
                              "user_details": {
                                "name": "John Smith",
                                "document_type": "ID",
                                "document_number": "CLM148418"
                              },
                              "status": "Declined",
                              "is_blocklisted": true,
                              "api_service": "ID_VERIFICATION",
                              "front_image_url": "https://<media-host>/document_front_2.jpg"
                            }
                          ],
                          "warnings": [
                            {
                              "feature": "ID_VERIFICATION",
                              "risk": "QR_NOT_DETECTED",
                              "additional_data": null,
                              "log_type": "information",
                              "short_description": "QR not detected",
                              "long_description": "The system couldn't find or read the QR code on the document, which is necessary for document verification. This could be due to poor image quality or an unsupported document type.",
                              "node_id": "feature_ocr_1"
                            }
                          ],
                          "verification_method": "document",
                          "assurance": "documentary",
                          "wallet_provider": null,
                          "fallback_from": null,
                          "id_lookup": null,
                          "wallet_verification": null,
                          "document_liveness": {
                            "portrait_replace": {
                              "score": 96.46,
                              "front": 96.46,
                              "back": 98.2,
                              "decline_threshold": 35,
                              "review_threshold": 70,
                              "bucket": "approve"
                            },
                            "printed_copy": {
                              "score": 91.2,
                              "front": 91.2,
                              "back": 93.7,
                              "decline_threshold": 35,
                              "review_threshold": 77,
                              "bucket": "approve"
                            },
                            "screen_replay": {
                              "score": 99.9,
                              "front": 99.9,
                              "back": 99.5,
                              "decline_threshold": 30,
                              "review_threshold": 70,
                              "bucket": "approve"
                            }
                          }
                        },
                        {
                          "node_id": "feature_ocr_2",
                          "status": "Approved",
                          "issuing_state": "ZAF",
                          "issuing_state_name": "South Africa",
                          "first_name": "Thabo",
                          "last_name": "Mokoena",
                          "full_name": "Thabo Mokoena",
                          "date_of_birth": "1991-06-15",
                          "personal_number": "9106155043088",
                          "verification_method": "id_lookup",
                          "assurance": "data_match",
                          "wallet_provider": null,
                          "fallback_from": null,
                          "id_lookup": {
                            "source": "Department of Home Affairs",
                            "checked_at": "2026-09-04T09:12:44Z",
                            "attempts": 1,
                            "max_attempts": 2,
                            "outcome": "match",
                            "comparison": [
                              {
                                "field": "identification_number",
                                "label": "ID number",
                                "provided": "9106155043088",
                                "record": "9106155043088",
                                "result": "match"
                              },
                              {
                                "field": "full_name",
                                "label": "Full name",
                                "provided": "Thabo Mokoena",
                                "record": "Thabo Mokoena",
                                "result": "match"
                              },
                              {
                                "field": "date_of_birth",
                                "label": "Date of birth",
                                "provided": "1991-06-15",
                                "record": "1991-06-15",
                                "result": "match"
                              }
                            ],
                            "registry_portrait": "https://<media-host>/registry_portrait.jpg",
                            "face_match_score": 96.4,
                            "source_errors": []
                          },
                          "wallet_verification": null,
                          "warnings": []
                        },
                        {
                          "node_id": "feature_ocr_3",
                          "status": "Approved",
                          "issuing_state": "DNK",
                          "issuing_state_name": "Denmark",
                          "first_name": "Freja",
                          "last_name": "Nielsen",
                          "full_name": "Freja Nielsen",
                          "date_of_birth": "1988-03-02",
                          "verification_method": "wallet",
                          "assurance": "cryptographic",
                          "wallet_provider": "mitid",
                          "fallback_from": null,
                          "id_lookup": null,
                          "wallet_verification": {
                            "provider": "mitid",
                            "provider_name": "MitID",
                            "issuing_authority": "Danish Agency for Digital Government",
                            "issuing_country": "DNK",
                            "credential_type": "person_identification",
                            "level_of_assurance": "substantial",
                            "verified_at": "2026-09-04T09:12:44Z",
                            "signature_valid": true,
                            "attributes": {
                              "full_name": "Freja Nielsen",
                              "date_of_birth": "1988-03-02",
                              "cpr_alias": "b0f1c2d3-e4f5-4678-9abc-def012345678"
                            },
                            "portrait": null,
                            "face_match_score": null
                          },
                          "warnings": []
                        }
                      ],
                      "nfc_verifications": [
                        {
                          "node_id": "feature_nfc_1",
                          "status": "In Review",
                          "is_nfc_skipped": false,
                          "skip_reason": null,
                          "chip_protocol": "icao",
                          "jpki": null,
                          "portrait_image": "https://<media-host>/portrait.jpg",
                          "signature_image": "https://<media-host>/signature.jpg",
                          "chip_data": {
                            "document_type": "ID",
                            "issuing_country": "ESP",
                            "document_number": "123456789",
                            "expiration_date": "2030-01-01",
                            "first_name": "John",
                            "last_name": "Smith",
                            "birth_date": "1990-05-15",
                            "gender": "M",
                            "nationality": "ESP",
                            "address": "CALLE MAYOR 123 4B, MADRID, MADRID",
                            "place_of_birth": "MADRID, MADRID"
                          },
                          "authenticity": {
                            "sod_integrity": true,
                            "dg_integrity": true
                          },
                          "certificate_summary": {
                            "issuer": "Common Name: CSCA SPAIN, Serial Number: 3, Organization: DIRECCION GENERAL DE LA POLICIA, Country: ES",
                            "subject": "Common Name: DS n-eID SPAIN 2, Organizational Unit: PASSPORT, Organization: DIRECCION GENERAL DE LA POLICIA, Country: ES",
                            "serial_number": "118120836164494130086420187336801405660",
                            "not_valid_after": "2031-02-18 10:21:11",
                            "not_valid_before": "2020-11-18 10:21:11"
                          },
                          "warnings": [
                            {
                              "feature": "NFC",
                              "risk": "DATA_INCONSISTENT",
                              "additional_data": null,
                              "log_type": "warning",
                              "short_description": "OCR and NFC mrz code extracted are not the same",
                              "long_description": "The Optical Character Recognition (OCR) data and the NFC chip data don't match, indicating potential document tampering or data inconsistency.",
                              "node_id": "feature_nfc_1"
                            }
                          ]
                        }
                      ],
                      "liveness_checks": [
                        {
                          "node_id": "feature_liveness_1",
                          "status": "Approved",
                          "method": "ACTIVE_3D",
                          "score": 89.92,
                          "reference_image": "https://<media-host>/reference.jpg",
                          "video_url": "https://<media-host>/video.mp4",
                          "age_estimation": 24.3,
                          "matches": [
                            {
                              "session_id": "7d4f1f60-9c2e-4b8a-8f3d-2a1b5c6d7e8f",
                              "session_number": 1234,
                              "vendor_data": "user_ref_001",
                              "verification_date": "2024-06-15T10:30:00Z",
                              "user_details": {
                                "full_name": "John Smith",
                                "document_type": "ID",
                                "document_number": "CLM148418"
                              },
                              "status": "Approved",
                              "is_blocklisted": false,
                              "is_allowlisted": false,
                              "api_service": null,
                              "source": "session",
                              "match_image_url": "https://<media-host>/face_match.jpg",
                              "similarity_percentage": 98.5
                            },
                            {
                              "session_id": "3e9a7c21-5b48-4f0e-9c6a-8d2f4b1e0a35",
                              "session_number": 1100,
                              "vendor_data": "customer_xyz",
                              "verification_date": "2024-04-10T09:15:00Z",
                              "user_details": {
                                "full_name": "John Smith",
                                "document_type": "P",
                                "document_number": "DZ8375806"
                              },
                              "status": "Approved",
                              "is_blocklisted": false,
                              "is_allowlisted": false,
                              "api_service": "PASSIVE_LIVENESS",
                              "source": "session",
                              "match_image_url": "https://<media-host>/face_match_2.jpg",
                              "similarity_percentage": 95.2
                            }
                          ],
                          "warnings": [
                            {
                              "feature": "LIVENESS",
                              "risk": "LOW_LIVENESS_SCORE",
                              "additional_data": null,
                              "log_type": "information",
                              "short_description": "Low liveness score",
                              "long_description": "The liveness check resulted in a low score, indicating potential use of non-live facial representations or poor-quality biometric data.",
                              "node_id": "feature_liveness_1"
                            }
                          ],
                          "face_quality": null,
                          "face_luminance": null
                        }
                      ],
                      "face_matches": [
                        {
                          "node_id": "feature_face_match_1",
                          "status": "In Review",
                          "score": 65.43,
                          "source_image_session_id": null,
                          "source_image": "https://<media-host>/source-image.jpg",
                          "target_image": "https://<media-host>/target-image.jpg",
                          "warnings": [
                            {
                              "feature": "FACEMATCH",
                              "risk": "LOW_FACE_MATCH_SIMILARITY",
                              "additional_data": null,
                              "log_type": "warning",
                              "short_description": "Low face match similarity",
                              "long_description": "The facial features of the provided image don't closely match the reference image, suggesting a potential identity mismatch.",
                              "node_id": "feature_face_match_1"
                            }
                          ]
                        }
                      ],
                      "phone_verifications": [
                        {
                          "node_id": "feature_phone_1",
                          "status": "Approved",
                          "phone_number_prefix": "+34",
                          "phone_number": "600600600",
                          "full_number": "+34600600600",
                          "country_code": "ES",
                          "country_name": "Spain",
                          "carrier": {
                            "name": "Orange",
                            "type": "mobile"
                          },
                          "is_disposable": false,
                          "is_virtual": false,
                          "verification_method": "sms",
                          "verification_attempts": 1,
                          "verified_at": "2024-07-28T06:47:35.654321Z",
                          "lifecycle": [
                            {
                              "type": "PHONE_VERIFICATION_MESSAGE_SENT",
                              "timestamp": "2025-08-24T09:12:39.580554+00:00",
                              "details": {
                                "status": "Success",
                                "reason": null,
                                "channel": "sms",
                                "actual_channel": "sms"
                              },
                              "fee": 0.1
                            },
                            {
                              "type": "VALID_CODE_ENTERED",
                              "timestamp": "2025-08-24T09:12:39.662157+00:00",
                              "details": {
                                "code_tried": "123456",
                                "status": "Approved"
                              },
                              "fee": 0
                            },
                            {
                              "type": "PHONE_VERIFICATION_APPROVED",
                              "timestamp": "2025-08-24T09:12:39.684292+00:00",
                              "details": null,
                              "fee": 0
                            }
                          ],
                          "warnings": [],
                          "matches": [
                            {
                              "session_id": null,
                              "session_number": null,
                              "vendor_data": null,
                              "verification_date": null,
                              "phone_number": "+34600000000",
                              "status": null,
                              "is_blocklisted": true,
                              "api_service": null,
                              "source": "list_entry"
                            }
                          ]
                        }
                      ],
                      "email_verifications": [
                        {
                          "node_id": "feature_email_1",
                          "status": "Approved",
                          "email": "test@example.com",
                          "is_breached": true,
                          "breaches": [
                            {
                              "name": "TAPAirPortugal",
                              "domain": "flytap.com",
                              "logo_path": "https://logos.example.com/TAPAirPortugal.png",
                              "breach_date": "2022-08-25",
                              "description": "In August 2022, the Portuguese airline <a href=\"https://www.bleepingcomputer.com/news/security/ragnar-locker-ransomware-claims-attack-on-portugals-flag-airline/\" target=\"_blank\" rel=\"noopener\">TAP Air Portugal was the target of a ransomware attack perpetrated by the Ragnar Locker gang</a> who later leaked the compromised data via a public dark web site. Over 5M unique email addresses were exposed alongside other personal data including names, genders, DoBs, phone numbers and physical addresses.",
                              "is_verified": true,
                              "data_classes": [
                                "dates_of_birth",
                                "email_addresses",
                                "genders",
                                "names",
                                "nationalities",
                                "phone_numbers",
                                "physical_addresses",
                                "salutations",
                                "spoken_languages"
                              ],
                              "breach_emails_count": 6083479
                            }
                          ],
                          "is_disposable": false,
                          "is_undeliverable": false,
                          "verification_attempts": 1,
                          "verified_at": "2025-09-15T17:36:19.963451Z",
                          "warnings": [
                            {
                              "feature": "EMAIL",
                              "risk": "BREACHED_EMAIL_DETECTED",
                              "additional_data": null,
                              "log_type": "information",
                              "short_description": "Breached email detected",
                              "long_description": "This email address was found in one or more known data breaches.",
                              "node_id": "feature_email_1"
                            }
                          ],
                          "lifecycle": [
                            {
                              "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
                              "timestamp": "2025-09-15T17:36:19.792684+00:00",
                              "details": {
                                "status": "Success",
                                "reason": null
                              },
                              "fee": 0.02
                            },
                            {
                              "type": "VALID_CODE_ENTERED",
                              "timestamp": "2025-09-15T17:36:19.963427+00:00",
                              "details": {
                                "code_tried": "123456",
                                "status": "Approved"
                              },
                              "fee": 0
                            },
                            {
                              "type": "EMAIL_VERIFICATION_DECLINED",
                              "timestamp": "2025-09-15T17:36:20.081471+00:00",
                              "details": {
                                "reason": "BREACHED_EMAIL_DETECTED"
                              },
                              "fee": 0
                            }
                          ],
                          "matches": [
                            {
                              "session_id": null,
                              "session_number": null,
                              "vendor_data": null,
                              "verification_date": null,
                              "email": "test@example.com",
                              "status": null,
                              "is_blocklisted": true,
                              "api_service": null,
                              "source": "list_entry"
                            }
                          ]
                        }
                      ],
                      "poa_verifications": [
                        {
                          "node_id": "feature_poa_1",
                          "status": "Declined",
                          "document_file": "https://<media-host>/poa_document.pdf",
                          "issuing_state": "AR",
                          "document_type": "UTILITY_BILL",
                          "document_subtype": null,
                          "document_language": "es",
                          "document_metadata": {
                            "file_size": 1000,
                            "content_type": "application/pdf",
                            "creation_date": "2021-01-01",
                            "modified_date": "2021-01-01",
                            "overlay_manipulation": null,
                            "creator": null,
                            "producer": "PDF Generator",
                            "software": null,
                            "encryption": null,
                            "is_signed": false,
                            "is_tampered": false,
                            "signature_info": null,
                            "exif_original_date": null,
                            "exif_digitized_date": null,
                            "processed_by_known_editor": false,
                            "has_different_creation_mod_date": true
                          },
                          "issuer": "Aguas del Norte",
                          "issue_date": "2021-02-01",
                          "expiration_date": null,
                          "poa_address": "AVDA. MONSEÑOR TAVELLA N° 3396, SALTA",
                          "poa_formatted_address": "Av. Monseñor Tavella 3396, A4400 Salta, Argentina",
                          "poa_parsed_address": {
                            "address_type": "Avenida",
                            "street_1": "Avenida Monseñor Tavella 3396",
                            "street_2": null,
                            "city": "Salta",
                            "region": "Salta",
                            "country": "AR",
                            "postal_code": "A4400",
                            "document_location": {
                              "latitude": -24.8208664,
                              "longitude": -65.4131
                            }
                          },
                          "name_on_document": "Fernando De Lima",
                          "name_match_score_expected_details": null,
                          "name_match_score_id_verification": 38.5,
                          "expected_details_address": null,
                          "expected_details_formatted_address": null,
                          "expected_details_parsed_address": {},
                          "extra_fields": {
                            "bank_account_number": "1234567890",
                            "bank_iban": null,
                            "bank_sort_code": null,
                            "bank_routing_number": null,
                            "bank_swift_bic": null,
                            "bank_branch_name": null,
                            "bank_branch_address": null,
                            "document_phone_number": "+5491112345678",
                            "additional_names": []
                          },
                          "extra_files": [
                            "https://<media-host>/extra_poa.pdf"
                          ],
                          "detected_codes": [
                            {
                              "type": "QR_CODE",
                              "page_number": 1,
                              "position": [
                                [
                                  820,
                                  1120
                                ],
                                [
                                  1002,
                                  1120
                                ],
                                [
                                  1002,
                                  1302
                                ],
                                [
                                  820,
                                  1302
                                ]
                              ],
                              "x": 820,
                              "y": 1120,
                              "width": 182,
                              "height": 182,
                              "page_width": 1190,
                              "page_height": 1684,
                              "raw_payload": "aHR0cHM6Ly9hZ3Vhc2RlbG5vcnRlLmNvbS9mYWN0dXJhLzk5ODgxMQ==",
                              "parsed_payload": "https://aguasdelnorte.com/factura/998811"
                            },
                            {
                              "type": "CODE_128",
                              "page_number": 1,
                              "position": [
                                [
                                  112,
                                  1480
                                ],
                                [
                                  560,
                                  1480
                                ],
                                [
                                  560,
                                  1540
                                ],
                                [
                                  112,
                                  1540
                                ]
                              ],
                              "x": 112,
                              "y": 1480,
                              "width": 448,
                              "height": 60,
                              "page_width": 1190,
                              "page_height": 1684,
                              "raw_payload": "MDA5OTg4MTEwMDA0Mg==",
                              "parsed_payload": "0099881100042"
                            }
                          ],
                          "warnings": []
                        }
                      ],
                      "document_ai_documents": [
                        {
                          "status": "Approved",
                          "node_id": "feature_document_ai_1",
                          "items": [
                            {
                              "uuid": "c1a2b3c4-d5e6-7f80-9a1b-2c3d4e5f6071",
                              "node_id": "feature_document_ai_1",
                              "document_key": "proof_of_funds",
                              "original_filename": "bank_statement.pdf",
                              "file_size": 184320,
                              "file_url": "https://<media-host>/document_ai/proof_of_funds.pdf",
                              "status": "Approved",
                              "extracted_data": {
                                "account_holder": "John Doe",
                                "balance": 15230.55,
                                "currency": "EUR",
                                "statement_date": "2026-05-31"
                              },
                              "detected_codes": [
                                {
                                  "type": "QR_CODE",
                                  "page_number": 2,
                                  "position": [
                                    [
                                      124,
                                      86
                                    ],
                                    [
                                      306,
                                      86
                                    ],
                                    [
                                      306,
                                      268
                                    ],
                                    [
                                      124,
                                      268
                                    ]
                                  ],
                                  "x": 124,
                                  "y": 86,
                                  "width": 182,
                                  "height": 182,
                                  "page_width": 1190,
                                  "page_height": 1684,
                                  "raw_payload": "SU5WLTIwMjYtMDA0Mg==",
                                  "parsed_payload": "INV-2026-0042"
                                }
                              ],
                              "fields": [
                                {
                                  "key": "account_holder",
                                  "name": "Account holder",
                                  "instruction": "Extract the full name of the account holder.",
                                  "type": "text",
                                  "required": true
                                },
                                {
                                  "key": "balance",
                                  "name": "Closing balance",
                                  "instruction": "Extract the closing balance amount.",
                                  "type": "number",
                                  "required": true
                                }
                              ],
                              "document_metadata": {
                                "is_tampered": false
                              },
                              "cross_check_result": null,
                              "created_at": "2026-06-01T12:34:56Z"
                            }
                          ],
                          "warnings": []
                        }
                      ],
                      "questionnaire_responses": [
                        {
                          "node_id": "feature_questionnaire_1",
                          "questionnaire_id": "9f7485e0-b00b-4d56-9d3e-7859b68d1213",
                          "title": "Source of Funds",
                          "description": "Reply to this questionnaire to help us understand the source of funds.",
                          "languages": [
                            "en"
                          ],
                          "default_language": "en",
                          "is_active": true,
                          "is_simple_questionnaire": true,
                          "questionnaire_group_id": "2b6a9d40-13a8-4b1e-9a6c-3f1d2e4b5a60",
                          "version": 1,
                          "published_at": "2025-11-02T09:14:55.000000Z",
                          "sections": [
                            {
                              "title": null,
                              "description": null,
                              "items": [
                                {
                                  "uuid": "618636d9-7d5c-41ce-b8d0-1ab2a4be20db",
                                  "value": "question_1",
                                  "element_type": "DROPDOWN",
                                  "is_required": true,
                                  "title": "What is your primary source of funds?",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": [
                                    {
                                      "label": "Salary",
                                      "value": "salary"
                                    },
                                    {
                                      "label": "Business Income",
                                      "value": "business_income"
                                    },
                                    {
                                      "label": "Savings",
                                      "value": "savings"
                                    },
                                    {
                                      "label": "Investments",
                                      "value": "investments"
                                    },
                                    {
                                      "label": "Sale of Asset",
                                      "value": "sale_of_asset"
                                    },
                                    {
                                      "label": "Inheritance/Gift",
                                      "value": "inheritance_gift"
                                    },
                                    {
                                      "label": "Pension",
                                      "value": "pension"
                                    },
                                    {
                                      "label": "Crypto Proceeds",
                                      "value": "crypto_proceeds"
                                    },
                                    {
                                      "label": "Other",
                                      "value": "other",
                                      "requires_text_input": true
                                    }
                                  ],
                                  "max_files": 1,
                                  "answer": {
                                    "value": "salary"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "2d16b527-72be-42e0-8e96-b164b818386c",
                                  "value": "question_2",
                                  "element_type": "LONG_TEXT",
                                  "is_required": true,
                                  "title": "Provide details of the primary source.",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": null,
                                  "max_files": 1,
                                  "answer": {
                                    "value": "Test answer"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "a9239b7c-fbfb-4ea7-b7e4-c835cd4016e0",
                                  "value": "question_3",
                                  "element_type": "DROPDOWN",
                                  "is_required": true,
                                  "title": "What is your annual income range (pre-tax)?",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": [
                                    {
                                      "label": "Less than $25,000",
                                      "value": "<25k"
                                    },
                                    {
                                      "label": "$25,000 - $50,000",
                                      "value": "25k-50k"
                                    },
                                    {
                                      "label": "$50,001 - $100,000",
                                      "value": "50k-100k"
                                    },
                                    {
                                      "label": "$100,001 - $250,000",
                                      "value": "100k-250k"
                                    },
                                    {
                                      "label": "More than $250,000",
                                      "value": ">250k"
                                    }
                                  ],
                                  "max_files": 1,
                                  "answer": {
                                    "value": "<25k"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "93dede62-6d0c-4a7f-934d-42175eb94011",
                                  "value": "question_4",
                                  "element_type": "DROPDOWN",
                                  "is_required": true,
                                  "title": "What is your approximate net worth (range)?",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": [
                                    {
                                      "label": "Less than $50,000",
                                      "value": "<50k"
                                    },
                                    {
                                      "label": "$50,000 - $250,000",
                                      "value": "50k-250k"
                                    },
                                    {
                                      "label": "$250,001 - $1,000,000",
                                      "value": "250k-1m"
                                    },
                                    {
                                      "label": "$1,000,001 - $5,000,000",
                                      "value": "1m-5m"
                                    },
                                    {
                                      "label": "More than $5,000,000",
                                      "value": ">5m"
                                    }
                                  ],
                                  "max_files": 1,
                                  "answer": {
                                    "value": "<50k"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "2af60d6f-6961-4692-9ee7-24b3033610a6",
                                  "value": "question_5",
                                  "element_type": "LONG_TEXT",
                                  "is_required": true,
                                  "title": "For your initial deposit/funding, indicate the exact source and amount.",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": null,
                                  "max_files": 1,
                                  "answer": {
                                    "value": "Test answer"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "0ad9d1aa-736f-46cf-947b-9e1241b53e40",
                                  "value": "question_6",
                                  "element_type": "LONG_TEXT",
                                  "is_required": true,
                                  "title": "Breakdown of sources by percentage.",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": null,
                                  "max_files": 1,
                                  "answer": {
                                    "value": "Test answer"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "1bf8a2a3-14ee-48a8-bb3d-175481aae4aa",
                                  "value": "question_7",
                                  "element_type": "SINGLE_CHOICE",
                                  "is_required": true,
                                  "title": "Will any funds originate from third parties? If yes, please provide details.",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": [
                                    {
                                      "label": "Yes",
                                      "value": "yes",
                                      "requires_text_input": true
                                    },
                                    {
                                      "label": "No",
                                      "value": "no"
                                    }
                                  ],
                                  "max_files": 1,
                                  "answer": {
                                    "text": "Additional details",
                                    "value": "yes"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "e18d4dd3-b7bf-4883-ba18-d6046adbe313",
                                  "value": "question_8",
                                  "element_type": "SINGLE_CHOICE",
                                  "is_required": true,
                                  "title": "Do you hold or plan to use virtual assets (e.g., crypto) to fund this account? If yes, please provide details.",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": [
                                    {
                                      "label": "Yes",
                                      "value": "yes",
                                      "requires_text_input": true
                                    },
                                    {
                                      "label": "No",
                                      "value": "no"
                                    }
                                  ],
                                  "max_files": 1,
                                  "answer": {
                                    "text": "Additional details",
                                    "value": "yes"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "a90a073d-e098-404c-bbce-5130d8b12a13",
                                  "value": "question_9",
                                  "element_type": "FILE_UPLOAD",
                                  "is_required": true,
                                  "title": "Upload a proof of funds document",
                                  "description": "You can upload your three (3) most recent bank statements, three (3) most recent payslips, your most recent tax return, proof of company ownership, trading exchange statement, sale of property, or proof of inheritance.",
                                  "placeholder": null,
                                  "choices": null,
                                  "max_files": 3,
                                  "answer": {
                                    "files": [
                                      "/media/ocr/",
                                      "/media/ocr/"
                                    ]
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                },
                                {
                                  "uuid": "9503b486-7cb8-4c3b-a97d-4b64926a5a47",
                                  "value": "question_10",
                                  "element_type": "LONG_TEXT",
                                  "is_required": false,
                                  "title": "Would you like to add any details to help us expedite our review of the documents you submitted?",
                                  "description": null,
                                  "placeholder": null,
                                  "choices": null,
                                  "max_files": 1,
                                  "answer": {
                                    "value": "Test answer"
                                  },
                                  "required_if": null,
                                  "repeatable_config": null
                                }
                              ]
                            }
                          ],
                          "status": "Approved"
                        }
                      ],
                      "aml_screenings": [
                        {
                          "node_id": "feature_aml_1",
                          "status": "In Review",
                          "total_hits": 1,
                          "entity_type": "person",
                          "hits": [
                            {
                              "id": "hit_7c1e9a40b2d35f86e0a4c912",
                              "url": "https://news.example.org/articles/sample",
                              "match": false,
                              "score": 0.73,
                              "target": null,
                              "caption": "Javier Ejemplo Modelo",
                              "datasets": [
                                "PEP"
                              ],
                              "features": null,
                              "rca_name": "",
                              "last_seen": "2025-06-13T00:00:00",
                              "risk_view": {
                                "crimes": {
                                  "score": 0,
                                  "weightage": 20,
                                  "risk_level": "Low",
                                  "risk_scores": {}
                                },
                                "countries": {
                                  "score": 0,
                                  "weightage": 30,
                                  "risk_level": "Low",
                                  "risk_scores": {}
                                },
                                "categories": {
                                  "score": 100,
                                  "weightage": 50,
                                  "risk_level": "High",
                                  "risk_scores": {
                                    "PEP": 100
                                  }
                                },
                                "custom_list": {}
                              },
                              "first_seen": "2025-01-18T00:00:00",
                              "properties": {
                                "name": [
                                  "Javier Ejemplo Modelo"
                                ],
                                "alias": [
                                  "Javier Ejemplo Modelo",
                                  "David Azagra"
                                ],
                                "notes": [
                                  "Spanish orchestra conductor"
                                ],
                                "title": null,
                                "gender": [
                                  "male"
                                ],
                                "height": null,
                                "topics": null,
                                "weight": null,
                                "address": null,
                                "country": null,
                                "website": null,
                                "eyeColor": null,
                                "keywords": null,
                                "lastName": [
                                  "Ejemplo",
                                  "Modelo"
                                ],
                                "position": null,
                                "religion": null,
                                "birthDate": [
                                  "1974"
                                ],
                                "education": [
                                  "Tokyo Arts and Space (2012-2012)",
                                  "Saint Petersburg Conservatory (-2010)",
                                  "Comillas Pontifical University"
                                ],
                                "ethnicity": null,
                                "firstName": [
                                  "David"
                                ],
                                "hairColor": null,
                                "weakAlias": null,
                                "birthPlace": [
                                  "Madrid"
                                ],
                                "modifiedAt": null,
                                "wikidataId": null,
                                "citizenship": null,
                                "nationality": null
                              },
                              "match_score": 98,
                              "risk_score": 73,
                              "review_status": "Unreviewed",
                              "score_breakdown": {
                                "name_score": 95,
                                "name_weight": 60,
                                "name_weight_normalized": 70.59,
                                "name_contribution": 67.06,
                                "dob_score": 100,
                                "dob_weight": 25,
                                "dob_weight_normalized": 29.41,
                                "dob_contribution": 29.41,
                                "country_score": 0,
                                "country_weight": 15,
                                "country_weight_normalized": 0,
                                "country_contribution": 0,
                                "document_number_match_type": "NEUTRAL",
                                "document_number_effect": "No document number provided for screening",
                                "total_score": 98
                              },
                              "pep_matches": [
                                {
                                  "aliases": [
                                    "Javier Ejemplo Modelo",
                                    "David Azagra"
                                  ],
                                  "education": [
                                    "Tokyo Arts and Space (2012-2012)",
                                    "Saint Petersburg Conservatory (-2010)",
                                    "Comillas Pontifical University"
                                  ],
                                  "list_name": "Wikidata",
                                  "publisher": "Wikidata",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "description": "Wikidata is the structured data project of the Wikipedia community, providing fact-based information edited by humans and machines",
                                  "matched_name": "Javier Ejemplo Modelo",
                                  "pep_position": "",
                                  "date_of_birth": "1974",
                                  "other_sources": [],
                                  "place_of_birth": "Madrid"
                                }
                              ],
                              "linked_entities": [
                                {
                                  "name": [
                                    "Antonio Ejemplo"
                                  ],
                                  "active": [],
                                  "status": [],
                                  "details": [],
                                  "relation": []
                                }
                              ],
                              "warning_matches": [],
                              "sanction_matches": [],
                              "adverse_media_details": {
                                "sentiment": "Moderately Negative",
                                "entity_type": "person",
                                "sentiment_score": -2,
                                "adverse_keywords": {
                                  "fraud": 3,
                                  "juicio": 1,
                                  "delitos": 2,
                                  "imputado": 1,
                                  "impunidad": 1,
                                  "corruption": 2,
                                  "favoritism": 2,
                                  "privilegio": 1,
                                  "corrupción": 1,
                                  "persecution": 2,
                                  "desconfianza": 1,
                                  "desprestigio": 1,
                                  "fraude de ley": 2,
                                  "manipulación": 1,
                                  "investigación": 3,
                                  "prevaricación": 8,
                                  "trato de favor": 1,
                                  "irregularidades": 2,
                                  "crisis de confianza": 1,
                                  "tráfico de influencias": 8
                                }
                              },
                              "adverse_media_matches": [
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo is implicated in legal violations related to favoritism and influence trafficking, leading to a negative portrayal in the article.",
                                  "headline": "La Diputación de Villaejemplo consolida la plaza a medida para el ex asesor de Moncloa amigo del \"hermanito\" de Ejemplo",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "fraud",
                                    "prevaricación",
                                    "tráfico de influencias",
                                    "irregularidades",
                                    "imputado"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-10T20:46:38"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo is implicated in legal issues regarding favoritism and corruption, leading to a negative portrayal in the article.",
                                  "headline": "La Diputación de Villaejemplo consolida la plaza a medida para el ex asesor de Moncloa amigo del \"hermanito\" de Ejemplo",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "fraud",
                                    "prevaricación",
                                    "tráfico de influencias",
                                    "irregularidades",
                                    "trato de favor"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-10T20:46:38"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo Modelo is mentioned in connection with Carlos Ficticio's corruption case, indicating his involvement in alleged influence peddling.",
                                  "headline": "España, paraíso del aforado",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "prevaricación",
                                    "tráfico de influencias",
                                    "corrupción",
                                    "impunidad",
                                    "privilegio",
                                    "desconfianza",
                                    "manipulación",
                                    "fraude de ley"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-10T05:05:34"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo Modelo is implicated in the same investigation as Ficticio, which raises questions about his conduct and political ethics.",
                                  "headline": "Aforamientos: esa figura incómoda",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "prevaricación",
                                    "tráfico de influencias",
                                    "investigación",
                                    "juicio",
                                    "fraude de ley",
                                    "desprestigio",
                                    "crisis de confianza",
                                    "delitos"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-08T06:01:00"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo is implicated in a legal investigation regarding irregularities in his hiring, which raises serious concerns about his conduct.",
                                  "headline": "La jueza del 'caso Javier Ejemplo' denuncia un «fraude de ley» en el aforamiento de Ficticio (Partido Ejemplo)",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "fraud",
                                    "irregularities",
                                    "prevaricación",
                                    "tráfico de influencias"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-09T10:19:10"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo Modelo is mentioned in connection with legal allegations of corruption, contributing to a negative perception.",
                                  "headline": "'Caso aforamiento': la letrada mayor de la Asamblea certifica a la juez que Ficticio es diputado desde antes de prometer su cargo en el Pleno",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "prevaricación",
                                    "tráfico de influencias"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-09T08:08:30"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo Modelo is implicated in the same investigation as Ficticio, raising concerns about political corruption and influence.",
                                  "headline": "Aforamientos: esa figura incómoda",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "prevaricación",
                                    "tráfico de influencias",
                                    "investigación"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-08T06:01:00"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo Modelo is implicated in the same investigation as Ficticio, which raises concerns about political misconduct.",
                                  "headline": "Aforamientos: esa figura incómoda",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "prevaricación",
                                    "tráfico de influencias",
                                    "investigación",
                                    "delitos"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-08T06:00:59"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo is implicated in a case of favoritism and corruption, which casts a negative light on his character and actions.",
                                  "headline": "'Caso Javier Ejemplo': las asociaciones judiciales salen en defensa de la juez Luisa Inventada ante las \"presiones externas\" que sufre",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "favoritism",
                                    "corruption",
                                    "persecution"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-06T10:08:15"
                                },
                                {
                                  "country": "spain",
                                  "summary": "Javier Ejemplo is implicated in a case of alleged favoritism and corruption, which casts a negative light on his character and actions.",
                                  "headline": "'Caso Javier Ejemplo': las asociaciones judiciales salen en defensa de la juez Luisa Inventada ante las \"presiones externas\" que sufre",
                                  "sentiment": "moderately negative",
                                  "thumbnail": "https://news.example.org/articles/sample",
                                  "source_url": "https://news.example.org/articles/sample",
                                  "author_name": null,
                                  "other_sources": [],
                                  "adverse_keywords": [
                                    "favoritism",
                                    "corruption",
                                    "persecution"
                                  ],
                                  "sentiment_score": -2,
                                  "publication_date": "2025-06-06T08:08:15"
                                }
                              ],
                              "additional_information": {}
                            }
                          ],
                          "score": 80,
                          "screened_data": {
                            "full_name": "Javier Ejemplo Modelo",
                            "nationality": "ES",
                            "date_of_birth": "1974-01-01",
                            "document_number": null
                          },
                          "is_ongoing_monitoring_enabled": true,
                          "next_ongoing_monitoring_bill_date": "2026-07-24",
                          "last_ongoing_screening_at": "2026-09-12T04:03:11Z",
                          "last_ongoing_screening_datasets_updated_at": "2026-09-11T06:00:00Z",
                          "warnings": [
                            {
                              "feature": "AML",
                              "risk": "POSSIBLE_MATCH_FOUND",
                              "additional_data": null,
                              "log_type": "warning",
                              "short_description": "Possible match found in AML screening",
                              "long_description": "The Anti-Money Laundering (AML) screening process identified potential matches with watchlists or high-risk databases, requiring further review.",
                              "node_id": "feature_aml_1"
                            }
                          ]
                        }
                      ],
                      "ip_analyses": [
                        {
                          "node_id": "feature_ip_1",
                          "status": "Approved",
                          "device_brand": "Apple",
                          "device_model": "iPhone",
                          "browser_family": "Mobile Safari",
                          "os_family": "iOS",
                          "platform": "mobile",
                          "device_fingerprint": "didit-fp-a1b2c3d4e5f6g7h8",
                          "ip_country": "Spain",
                          "ip_country_code": "ES",
                          "ip_state": "Barcelona",
                          "ip_city": "Barcelona",
                          "latitude": 41.4022,
                          "longitude": 2.1407,
                          "ip_address": "83.50.226.71",
                          "isp": null,
                          "organization": null,
                          "is_vpn_or_tor": false,
                          "is_data_center": false,
                          "time_zone": "Europe/Madrid",
                          "time_zone_offset": "+0100",
                          "ip": {
                            "location": {
                              "latitude": 40.2206327,
                              "longitude": 1.5770097
                            },
                            "distance_from_id_document": 23.4,
                            "distance_from_poa_document": 12.3
                          },
                          "id_document": {
                            "location": {
                              "latitude": 41.2706327,
                              "longitude": 1.9770097
                            },
                            "distance_from_ip": 23.4,
                            "distance_from_poa_document": 18.7
                          },
                          "poa_document": {
                            "location": {
                              "latitude": 41.2706327,
                              "longitude": 1.9770097
                            },
                            "distance_from_ip": 12.3,
                            "distance_from_id_document": 18.7
                          },
                          "warnings": [],
                          "matches": [
                            {
                              "session_id": "99999999-8888-7777-6666-555555555555",
                              "session_number": 41205,
                              "vendor_data": "22222222-2222-2222-2222-222222222222",
                              "verification_date": "2024-07-20T10:15:30Z",
                              "match_type": "ip_address",
                              "match_source": "ip_address",
                              "matched_value": "83.50.226.71",
                              "status": "Approved",
                              "is_blocklisted": false,
                              "api_service": null,
                              "source": "session",
                              "device_info": {
                                "device_brand": "Apple",
                                "device_model": "iPhone",
                                "browser_family": "Mobile Safari",
                                "os_family": "iOS",
                                "platform": "mobile",
                                "device_fingerprint": "didit-fp-f9e8d7c6b5a40312"
                              },
                              "location_info": {
                                "ip_address": "83.50.226.71",
                                "ip_country": "Spain",
                                "ip_country_code": "ES",
                                "ip_state": "Barcelona",
                                "ip_city": "Barcelona",
                                "is_vpn_or_tor": false,
                                "is_data_center": false
                              },
                              "confidence": 0.0,
                              "match_mode": "co_occurrence"
                            },
                            {
                              "session_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                              "session_number": 42830,
                              "vendor_data": "33333333-3333-3333-3333-333333333333",
                              "verification_date": "2024-06-30T18:22:05Z",
                              "match_type": "device_fingerprint",
                              "match_source": "recovered_high",
                              "matched_value": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
                              "status": "Declined",
                              "is_blocklisted": false,
                              "api_service": null,
                              "source": "session",
                              "device_info": {
                                "device_brand": "Samsung",
                                "device_model": "SM-G991B",
                                "browser_family": "Chrome Mobile",
                                "os_family": "Android",
                                "platform": "mobile",
                                "device_fingerprint": null
                              },
                              "location_info": {
                                "ip_address": "83.50.231.18",
                                "ip_country": "Spain",
                                "ip_country_code": "ES",
                                "ip_state": "Madrid",
                                "ip_city": "Madrid",
                                "is_vpn_or_tor": false,
                                "is_data_center": false
                              },
                              "confidence": 1.0,
                              "match_mode": "deterministic",
                              "recovery_similarity": 0.9874,
                              "tls_ja4_corroborated": true,
                              "recovery_gate_reason": "hardware_root_match"
                            }
                          ]
                        }
                      ],
                      "database_validations": [
                        {
                          "node_id": "feature_db_validation_1",
                          "issuing_state": "BRA",
                          "validation_type": "one_by_one",
                          "screened_data": {
                            "last_name": "De Lima",
                            "first_name": "Fernando",
                            "tax_number": "01234567890",
                            "date_of_birth": "1980-01-01",
                            "document_type": "ID",
                            "expiration_date": "2030-01-01"
                          },
                          "validations": [
                            {
                              "service_id": "bra_cpf",
                              "service_name": "Brazil - CPF status check",
                              "outcome_code": "MATCH",
                              "validation": {
                                "full_name": "full_match",
                                "date_of_birth": "full_match",
                                "identification_number": "full_match"
                              },
                              "source_data": {
                                "identification_number": "01234567890",
                                "first_name": "FERNANDO",
                                "last_name": "DE LIMA",
                                "date_of_birth": "1980-01-01",
                                "gender": "M",
                                "nationality": "BRA"
                              }
                            }
                          ],
                          "match_type": "full_match",
                          "status": "Approved",
                          "warnings": []
                        }
                      ],
                      "reviews": [
                        {
                          "user": "compliance@example.com",
                          "new_status": "Declined",
                          "comment": "Possible match found in AML screening",
                          "created_at": "2024-07-18T13:29:00.366811Z"
                        }
                      ],
                      "created_at": "2024-07-24T08:54:25.443172Z",
                      "expires_at": "2025-07-24T08:54:25.443172Z",
                      "biometric_consent": {
                        "required": false,
                        "trigger": null,
                        "status": "not_required",
                        "given_at": null,
                        "declined_at": null,
                        "text_version": null,
                        "text_hash": null,
                        "locale": null,
                        "policy_url": null,
                        "step": null,
                        "node_id": null,
                        "ip_address": null,
                        "ip_country_code": null,
                        "ip_state": null,
                        "ip_city": null,
                        "user_agent": null,
                        "detected_ip_address": "83.50.226.71",
                        "detected_country_code": "ES",
                        "detected_state": "ES-B",
                        "detected_city": "Barcelona",
                        "declared_state": null,
                        "document_state": null,
                        "jurisdictions": [],
                        "retention_months": null,
                        "reason": null,
                        "decline_reason": null,
                        "face_data_deleted_at": null
                      }
                    }
                  },
                  "BusinessExample": {
                    "summary": "Exemple de session entreprise (KYB)",
                    "description": "Une décision avec `session_kind = \"business\"` : les sessions KYB remplacent les tableaux de fonctionnalités KYC par `registry_checks`, `document_verifications` et `key_people_checks`, tout en partageant `aml_screenings`, `phone_verifications`, `email_verifications`, `questionnaire_responses`, `ip_analyses`, `reviews` et l'enveloppe de session.",
                    "value": {
                      "session_id": "66666666-7777-8888-9999-000000000000",
                      "session_kind": "business",
                      "session_number": 31415,
                      "session_url": "https://verify.didit.me/session/business123",
                      "status": "In Review",
                      "environment": "live",
                      "workflow_id": "abababab-cdcd-efef-0101-232323232323",
                      "features": [
                        "KYB_REGISTRY",
                        "KYB_DOCUMENTS",
                        "KYB_KEY_PEOPLE"
                      ],
                      "vendor_data": "merchant-001234",
                      "metadata": null,
                      "callback": "https://example.com/verification/callback",
                      "registry_checks": [
                        {
                          "status": "Approved",
                          "node_id": "feature_kyb_registry_1",
                          "data_resolved": true,
                          "company": {
                            "uuid": "dddd4444-eeee-5555-ffff-666677778888",
                            "node_id": "feature_kyb_registry_1",
                            "status": "Approved",
                            "registry_status": "active",
                            "data_resolved": true,
                            "company_name": "ACME HOLDINGS LTD",
                            "registration_number": "12345678",
                            "country_code": "GB",
                            "region": null,
                            "company_type": "Private Limited Company",
                            "incorporation_date": "2015-03-12",
                            "registered_address": "1 Example Street, London, EC1A 1AA",
                            "tax_number": null,
                            "risk_level": null,
                            "verification_status": "verified",
                            "is_from_registry": true,
                            "fetch_status": "resolved",
                            "alternative_names": null,
                            "nature_of_business": "62012 - Business and domestic software development",
                            "registered_capital": "100 GBP",
                            "registered_capital_amount": "100.00",
                            "registered_capital_currency": "GBP",
                            "website": null,
                            "email": null,
                            "phone": null,
                            "legal_entity_identifier": null,
                            "location_of_registration": "England and Wales",
                            "financial_summary": null,
                            "officers": [
                              {
                                "uuid": "aaaa1111-bbbb-2222-cccc-333344445555",
                                "name": "Jane Smith",
                                "designation": "Director",
                                "role": "director",
                                "nationality": "British",
                                "is_active": true,
                                "kyc_status": "Approved",
                                "kyc_session_url": "https://verify.didit.me/session/abc123def456"
                              }
                            ],
                            "beneficial_owners": [
                              {
                                "uuid": "bbbb2222-cccc-3333-dddd-444455556666",
                                "name": "John Doe",
                                "first_name": "John",
                                "last_name": "Doe",
                                "entity_type": "person",
                                "roles": [
                                  "ubo",
                                  "shareholder"
                                ],
                                "ownership_min_shares": "50",
                                "ownership_max_shares": "75",
                                "is_active": true,
                                "kyc_status": "Pending",
                                "kyc_session_url": "https://verify.didit.me/session/def456ghi789",
                                "effective_ownership_percent": 75.0
                              }
                            ],
                            "addresses": [
                              {
                                "type": "registered",
                                "address": "1 Example Street, London, EC1A 1AA",
                                "country": "GB"
                              }
                            ],
                            "industries": [
                              {
                                "code": "62012",
                                "description": "Business and domestic software development"
                              }
                            ],
                            "accounts": null,
                            "registry_data": {},
                            "user_provided_data": {
                              "company_name": "ACME HOLDINGS",
                              "registration_number": "12345678"
                            },
                            "confirmed_by_user_at": "2026-06-10T12:01:30.000000Z",
                            "last_console_edit_at": null,
                            "is_editable": false
                          },
                          "ownership_structure": {
                            "shareholders": [
                              {
                                "name": "John Doe",
                                "first_name": "John",
                                "last_name": "Doe",
                                "date_of_birth": null,
                                "country_of_birth": null,
                                "company_name": null,
                                "registration_number": null,
                                "entity_type": "person",
                                "nationality": null,
                                "designation": null,
                                "roles": [
                                  "shareholder"
                                ],
                                "ownership_min_shares": "75",
                                "ownership_max_shares": "75",
                                "voting_min_shares": null,
                                "voting_max_shares": null,
                                "appointment_date": null,
                                "is_active": true,
                                "shareholding": {
                                  "share_class": "ORDINARY",
                                  "number_of_shares": 750.0,
                                  "currency": "GBP",
                                  "nominal_value": 1.0,
                                  "total_value": null,
                                  "percentage": 75.0
                                }
                              }
                            ],
                            "beneficial_owners": []
                          },
                          "warnings": []
                        }
                      ],
                      "aml_screenings": null,
                      "document_verifications": [
                        {
                          "status": "In Review",
                          "node_id": "feature_kyb_documents_1",
                          "items": [
                            {
                              "uuid": "eeee5555-ffff-6666-0000-777788889999",
                              "document_type": "LEGAL_PRESENCE",
                              "document_subtype": "CERTIFICATE_OF_INCORPORATION",
                              "document_group": "LEGAL_PRESENCE",
                              "file_url": "https://<media-host>/kyb/certificate-of-incorporation.pdf",
                              "original_filename": "certificate_of_incorporation.pdf",
                              "file_size": 482133,
                              "status": "Approved",
                              "created_at": "2026-06-10T12:03:11.000000Z",
                              "cross_check_result": {
                                "critical": {
                                  "company_name": {
                                    "document": "ACME HOLDINGS LTD",
                                    "registry": "ACME HOLDINGS LTD",
                                    "score": 1.0,
                                    "match": true
                                  },
                                  "registration_number": {
                                    "document": "12345678",
                                    "registry": "12345678",
                                    "match": true
                                  }
                                },
                                "non_critical": {},
                                "people": {}
                              },
                              "document_metadata": {
                                "file_size": 482133,
                                "content_type": "application/pdf",
                                "creation_date": "2015-03-12T09:00:00",
                                "modified_date": "2015-03-12T09:00:00",
                                "creator": null,
                                "producer": null,
                                "software": null,
                                "encryption": null,
                                "is_signed": true,
                                "is_tampered": false,
                                "signature_info": null,
                                "exif_original_date": null,
                                "exif_digitized_date": null,
                                "processed_by_known_editor": false,
                                "has_different_creation_mod_date": false,
                                "overlay_manipulation": null
                              },
                              "description": null,
                              "is_requested": false,
                              "ocr_data": {
                                "company_name": "ACME HOLDINGS LTD",
                                "registration_number": "12345678",
                                "incorporation_date": "2015-03-12"
                              },
                              "is_console_upload": false,
                              "is_confirmed": true
                            },
                            {
                              "uuid": "ffff6666-0000-7777-1111-888899990000",
                              "document_type": "OWNERSHIP_STRUCTURE",
                              "document_subtype": null,
                              "document_group": "OWNERSHIP_STRUCTURE",
                              "file_url": null,
                              "original_filename": null,
                              "file_size": null,
                              "status": "Not Finished",
                              "created_at": "2026-06-10T15:40:02.000000Z",
                              "cross_check_result": null,
                              "document_metadata": null,
                              "description": "Please upload an up-to-date shareholder registry",
                              "is_requested": true,
                              "ocr_data": null,
                              "is_console_upload": false,
                              "is_confirmed": true
                            }
                          ],
                          "groups": {
                            "LEGAL_PRESENCE": {
                              "total": 1,
                              "approved": 1,
                              "pending": 0,
                              "declined": 0,
                              "in_review": 0,
                              "other": 0,
                              "missing": 0
                            },
                            "OWNERSHIP_STRUCTURE": {
                              "total": 1,
                              "approved": 0,
                              "pending": 0,
                              "declined": 0,
                              "in_review": 0,
                              "other": 0,
                              "missing": 1
                            }
                          },
                          "required_groups": [
                            "LEGAL_PRESENCE",
                            "OWNERSHIP_STRUCTURE"
                          ],
                          "warnings": []
                        }
                      ],
                      "key_people_checks": [
                        {
                          "status": "In Review",
                          "node_id": "feature_kyb_key_people_1",
                          "registry": {
                            "officers": [
                              {
                                "uuid": "aaaa1111-bbbb-2222-cccc-333344445555",
                                "name": "Jane Smith",
                                "designation": "Director",
                                "role": "director",
                                "nationality": "British",
                                "appointment_date": "2015-03-12",
                                "termination_date": null,
                                "is_active": true,
                                "address": "1 Example Street, London, EC1A 1AA",
                                "aml_status": "Approved",
                                "kyc_status": "Approved",
                                "kyc_session_url": "https://verify.didit.me/session/abc123def456",
                                "kyc_session_id": "77777777-8888-9999-aaaa-bbbbbbbbbbbb",
                                "verification_workflow_type": "kyc",
                                "verification_workflow_id": "12121212-3434-5656-7878-909090909090",
                                "verification_workflow_label": "Key People KYC",
                                "verification_workflow_features": [
                                  {
                                    "feature": "ID_VERIFICATION",
                                    "status": "Approved"
                                  },
                                  {
                                    "feature": "LIVENESS",
                                    "status": "Approved"
                                  },
                                  {
                                    "feature": "AML",
                                    "status": "Approved"
                                  }
                                ],
                                "didit_internal_id": "99999999-0000-1111-2222-333333333333",
                                "kyc_document_type": "P",
                                "kyc_nationality": "GBR",
                                "kyc_liveness_passed": true,
                                "kyc_verified_at": "2026-06-10T14:22:31.123456Z",
                                "kyc_aml_categories": {
                                  "sanctions": "clear",
                                  "pep": "clear",
                                  "adverse_media": "clear",
                                  "warnings": "clear"
                                },
                                "kyc_notification_sent_at": "2026-06-09T09:00:00.000000Z"
                              }
                            ],
                            "beneficial_owners": [
                              {
                                "uuid": "bbbb2222-cccc-3333-dddd-444455556666",
                                "name": "John Doe",
                                "first_name": "John",
                                "last_name": "Doe",
                                "date_of_birth": "1980-05-04",
                                "country_of_birth": null,
                                "email": null,
                                "company_name": null,
                                "registration_number": null,
                                "entity_type": "person",
                                "nationality": "British",
                                "designation": null,
                                "roles": [
                                  "ubo",
                                  "shareholder"
                                ],
                                "ownership_min_shares": "50",
                                "ownership_max_shares": "75",
                                "is_active": true,
                                "aml_status": null,
                                "kyc_status": "In Progress",
                                "kyc_session_url": "https://verify.didit.me/session/def456ghi789",
                                "kyc_session_id": "88888888-9999-aaaa-bbbb-cccccccccccc",
                                "verification_workflow_type": "kyc",
                                "verification_workflow_id": "12121212-3434-5656-7878-909090909090",
                                "verification_workflow_label": "Key People KYC",
                                "verification_workflow_features": [
                                  {
                                    "feature": "ID_VERIFICATION",
                                    "status": "Not Finished"
                                  },
                                  {
                                    "feature": "LIVENESS",
                                    "status": "Not Finished"
                                  },
                                  {
                                    "feature": "AML",
                                    "status": "Not Finished"
                                  }
                                ],
                                "didit_internal_id": null,
                                "kyc_document_type": null,
                                "kyc_nationality": null,
                                "kyc_liveness_passed": null,
                                "kyc_verified_at": null,
                                "kyc_aml_categories": null,
                                "kyc_notification_sent_at": null,
                                "child_beneficial_owners": [],
                                "effective_ownership_percent": 75.0
                              }
                            ]
                          },
                          "submitted": {
                            "parties": [
                              {
                                "uuid": "cccc3333-dddd-4444-eeee-555566667777",
                                "entity_type": "person",
                                "source": "USER",
                                "name": "John Doe",
                                "first_name": "John",
                                "last_name": "Doe",
                                "company_name": null,
                                "registration_number": null,
                                "email": "john.doe@example.com",
                                "nationality": "GBR",
                                "phone_number": "+447700900123",
                                "date_of_birth": "1980-05-04",
                                "position": "Chief Executive Officer",
                                "custom_fields": {},
                                "is_active": true,
                                "is_skipped": false,
                                "requires_verification": true,
                                "roles": [
                                  {
                                    "role": "ubo",
                                    "ownership_percent": 75.0,
                                    "voting_percent": 75.0
                                  },
                                  {
                                    "role": "director",
                                    "ownership_percent": null,
                                    "voting_percent": null
                                  }
                                ],
                                "kyc_session_id": "88888888-9999-aaaa-bbbb-cccccccccccc",
                                "kyc_session_status": "In Progress",
                                "kyc_session_url": "https://verify.didit.me/session/def456ghi789",
                                "kyb_sub_session_id": null,
                                "kyb_sub_session_status": null,
                                "kyb_sub_session_url": null,
                                "verification_workflow_type": "kyc",
                                "verification_workflow_id": "12121212-3434-5656-7878-909090909090",
                                "verification_workflow_label": "Key People KYC",
                                "verification_workflow_features": [
                                  {
                                    "feature": "ID_VERIFICATION",
                                    "status": "Not Finished"
                                  },
                                  {
                                    "feature": "LIVENESS",
                                    "status": "Not Finished"
                                  },
                                  {
                                    "feature": "AML",
                                    "status": "Not Finished"
                                  }
                                ],
                                "didit_internal_id": null
                              }
                            ]
                          },
                          "ubo_kyc_summary": {
                            "total": 1,
                            "approved": 0,
                            "flagged": 0,
                            "pending": 1
                          },
                          "warnings": []
                        }
                      ],
                      "phone_verifications": null,
                      "email_verifications": null,
                      "questionnaire_responses": null,
                      "ip_analyses": null,
                      "reviews": [],
                      "contact_details": null,
                      "expected_details": {
                        "company_name": "Tesco PLC",
                        "registry_country": "GB",
                        "registration_number": "00445790"
                      },
                      "created_at": "2026-06-10T11:58:04.000000Z",
                      "expires_at": "2026-06-24T11:58:04.000000Z"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SessionDecision"
                }
              }
            }
          },
          "403": {
            "description": "Échec de l'authentification ou de l'autorisation. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Deux chaînes `detail` distinguent les modes d'échec :\n\n- `\"Authentication credentials were not provided or are invalid.\"` — aucun en-tête `x-api-key` (et aucun token `Authorization: Bearer`), ou l'identifiant fourni a échoué à l'introspection (révoqué, expiré ou malformé).\n- `\"You do not have permission to perform this action.\"` — l'identifiant est valide mais n'a pas l'autorisation de lire cette session : un token Bearer d'utilisateur de la console n'a pas l'autorisation `read:sessions` ou ne peut pas accéder à l'application propriétaire, ou une clé API appartient à une autre organisation que la session.\n\nNotez que pour un `sessionId` totalement inconnu, l'endpoint résout l'application propriétaire avant de valider les identifiants, de sorte qu'une session manquante renvoie `404` même lorsque l'identifiant est manquant ou invalide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Authentication credentials were not provided or are invalid."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou l'introspection de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Insufficient permissions": {
                    "summary": "Identifiant valide ne disposant pas de read:sessions ou d'un accès à l'application propriétaire",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Session introuvable. Renvoyé lorsqu'aucune session active ne correspond au `sessionId` fourni, qu'il s'agisse d'une session de vérification des utilisateurs (KYC) ou de vérification d'entreprise (KYB) — une session ayant été supprimée aboutit également ici. Le corps est l'enveloppe standard `{\"detail\": ...}`.\n\n**Deux chaînes `detail` distinctes.** Si le `sessionId` est inconnu à la fois en tant que session KYC et KYB, la recherche de propriétaire préalable à l'authentification échoue et vous recevez `{\"detail\": \"Not found.\"}` — cela se produit avant la validation des identifiants, c'est donc renvoyé même pour les appels non authentifiés. Si la session existe mais ne peut pas être récupérée sous l'application authentifiée (par exemple un enregistrement obsolète ou venant d'être supprimé), la vue renvoie `{\"detail\": \"Session not found.\"}`. Les deux indiquent le même résultat — la session n'est pas accessible — basez-vous donc sur le code de statut `404` plutôt que sur la chaîne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Not found."
                    }
                  }
                },
                "examples": {
                  "Unknown session id": {
                    "summary": "sessionId est inconnu pour cette application",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Session not retrievable": {
                    "summary": "La session existe mais ne peut pas être récupérée pour cette application",
                    "value": {
                      "detail": "Session not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les requêtes GET sont limitées à **600 par minute par identifiant d'authentification** (clé API, token Bearer ou IP source en cas de requête non authentifiée). Examinez `Retry-After` / `X-RateLimit-Reset` et temporisez avant de réessayer. Si vous atteignez cette limite en effectuant du polling pour obtenir les décisions, passez au webhook `status.updated` et récupérez la décision une seule fois par changement de statut.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer la requête.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Nombre maximal de requêtes autorisées dans la fenêtre actuelle (600 pour les requêtes GET).",
                "schema": {
                  "type": "integer",
                  "example": 600
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Horodatage Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1750000000
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Explication lisible par l'humain du dépassement de la limite de débit.",
                      "example": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "summary": "Plus de 600 requêtes GET en une minute avec le même identifiant",
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification dont vous souhaitez récupérer la décision. Il s'agit du `session_id` renvoyé par `POST /v3/session/`. Le même chemin fonctionne pour les sessions de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) — le serveur résout l'identifiant pour les deux types de session.\n\n**Doit être un UUID valide.** La route ne correspond qu'aux UUID bien formés ; une valeur malformée est donc rejetée par le routeur d'URL avant l'exécution de tout code d'application et la réponse est une page **HTML** `404` plutôt que l'enveloppe JSON `{\"detail\": ...}` illustrée ci-dessous. Validez le format de l'UUID côté client afin de distinguer une erreur de saisie d'un véritable `404` pour session introuvable.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Liste séparée par des virgules de sections de payload supplémentaires. Valeurs prises en charge : `events` et `resubmissions`, seules ou combinées (`events,resubmissions`). Lorsque `include=events` est transmis, la réponse contient en plus la chronologie des événements de session (`events`, y compris les événements de routage `WORKFLOW_BRANCH_EVALUATED` / `WORKFLOW_STATUS_NODE_REACHED` décrits sur la page Récupérer une session), le journal d'activité complet (`activity_reviews`), les indicateurs de liste de blocage (`blocklisted`), un détail des coûts par session (`cost_breakdown`), les métadonnées de workflow (`workflow_type`, `workflow_version`, `workflow_version_id` et `workflow_terminal_node_id` - le dernier nœud de statut de workflow enregistré ayant défini un statut de session, ou `null` si aucun n'a été enregistré ; provenance historique qui n'est pas effacée par les approbations, refus ou nouvelles soumissions manuels, et qui est remplacée par un nœud de statut de workflow ultérieur), ainsi que les métadonnées de session (`api_service` — chaîne ou `null`, défini uniquement pour les sessions d'API autonome ; `session_type` — `API`, `HOSTED` ou `MIGRATED` ; `has_device_nfc_support` — booléen). Deux champs changent par rapport à la structure standard : le discriminateur de niveau supérieur `session_kind` est **omis** (la structure avec événements n'existe que pour les sessions utilisateur), et le tableau `features` passe de chaînes simples à des objets `{feature, node_id}` — où la fonctionnalité d'e-mail est indiquée comme `EMAIL` au lieu de `EMAIL_VERIFICATION`. Cette structure enrichie est principalement utilisée par la console Didit ; la plupart des intégrations d'API doivent omettre ce paramètre. **Limitation KYB :** `include=events` ne s'applique qu'aux sessions utilisateur (KYC). Les sessions d'entreprise (`session_kind = \"business\"`) renvoient toujours la structure de décision d'entreprise standard — `events`, `activity_reviews`, `blocklisted`, `cost_breakdown` et les métadonnées supplémentaires `workflow_*`/session ne sont jamais renvoyés pour les sessions d'entreprise, et leur tableau `features` reste un tableau de chaînes simples. Avec `include=resubmissions` (sessions utilisateur comme entreprise), la réponse contient également `resubmissions` : une entrée par demande de nouvelle soumission, de la plus ancienne à la plus récente, chacune avec `number`, `created_at`, `previous_status`, `nodes`, `reasons`, `requested_by` et `results` (ce que les étapes soumises à nouveau ont renvoyé avant la demande, sous les mêmes clés et dans la même structure que les résultats actuels). Chaque élément de `cost_breakdown` comporte `usage_type`, `price`, `details` et `created_at` : une étape soumise à nouveau qui est exécutée une seconde fois est facturée comme un nouvel élément.",
            "schema": {
              "type": "string",
              "enum": [
                "events",
                "resubmissions",
                "events,resubmissions"
              ],
              "example": "events"
            }
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X GET 'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/decision/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Accept: application/json'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.retrieve_decision(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.retrieveDecision(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.RetrieveDecision(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsRetrieveDecisionParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().retrieveDecision(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->retrieveDecision('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.retrieve_decision(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.RetrieveDecisionAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/delete/": {
      "delete": {
        "summary": "Supprimer une session de vérification (KYC ou KYB)",
        "description": "Supprimez une session de vérification unique, Vérification des utilisateurs (KYC) ou Vérification d'entreprise (KYB), par son `session_id`. L'identifiant est d'abord résolu parmi les sessions KYC, puis les sessions KYB, de sorte que les deux types sont supprimés via cette URL unique.\n\n**Ce qui est supprimé :**\n- La session et chaque tentative de vérification qu'elle contient, y compris les résultats remplacés par une nouvelle soumission : la décision, les données extraites, tous les enregistrements de fonctionnalités associés (vérification d'identité, visage, détection du vivant, correspondance faciale, filtrage AML, vérifications de registre, analyse de l'IP, etc.), ses examens et son journal d'activité.\n- Tous les fichiers stockés appartenant à la session : photos recto/verso du document (versions intégrales, recadrées et floutées pour des raisons de confidentialité), vidéos de capture du document, recadrages de portrait, images de portrait et de signature de la puce NFC, images de référence du visage, vidéos de détection du vivant, images source/cible de correspondance faciale, justificatifs de domicile et tout fichier supplémentaire importé (KYC) ; documents d'entreprise importés et fichiers supplémentaires (KYB). Documents de signature électronique, PDF signés, PDF de preuves et images de signature (KYC et KYB) : leurs chemins de téléchargement cessent de fonctionner. Les URL de médias précédemment émises (`https://<media-host>/...`) ne sont plus résolues.\n- Les données faciales de la session. Son embedding facial est également supprimé, sauf si vous choisissez de conserver un gabarit sans image (voir **Données biométriques faciales**).\n- Les livraisons de webhooks encore en file d'attente pour la session, ainsi que leurs réessais. Les webhooks déjà livrés ne sont pas affectés.\n- Pour une session de Vérification d'entreprise (KYB) : les vérifications créées pour ses personnes clés (KYC) et ses propriétaires personnes morales (KYB), de manière récursive, signalées sous `deleted_child_verifications`. Une vérification à laquelle elle est uniquement liée, comme un KYC approuvé existant qu'elle a réutilisé, n'est pas supprimée.\n\nLa session disparaît immédiatement de tous les endpoints de lecture : `GET /v3/session/{sessionId}/decision/` renvoie `404` et `GET /v3/sessions/` cesse de la lister. La surveillance AML continue et la surveillance de registre KYB initiées par les vérifications supprimées s'arrêtent.\n\n**Ce qui n'est pas affecté :** les entrées de liste de blocage créées à partir de cette session (visage ou document) ne sont **pas** supprimées ; gérez-les avec les endpoints de liste de blocage. Les tokens de partage émis pour la session ne sont pas révoqués, mais ils n'ont plus rien à importer : un import avec l'un d'eux renvoie `400` avec `{\"share_token\": [\"Original session does not exist.\"]}`. Les crédits déjà consommés ne sont **pas** remboursés. L'entité parente Utilisateur ou Entreprise n'est **pas** supprimée ; utilisez `POST /v3/users/delete/` ou `POST /v3/businesses/delete/` pour celles-ci. Si le portrait de profil de l'utilisateur provenait de cette session, le portrait est supprimé avec elle.\n\n**Données biométriques faciales :** par défaut, l'embedding facial de la session est supprimé avec la session (`face_retention_outcome: deleted`). Une application ayant activé la conservation du gabarit biométrique (`face_retention_policy: retain_until_user_deleted` sur `PATCH /v3/webhook/`), ou une requête avec `retain_face_embeddings: true`, conserve un gabarit biométrique facial sans image géré séparément, associé à l'utilisateur de la session (`retained_with_user`), afin que la détection de doublons, la Recherche faciale et l'authentification biométrique continuent de fonctionner. Le gabarit ne contient jamais l'image du visage, les médias, les champs d'identité, la décision ni l'identifiant de la session supprimée ; il s'agit de données biométriques supprimées à `biometric_template_expires_at`, ou plus tôt lors de la suppression de l'utilisateur, d'un effacement pour raisons de confidentialité ou d'une purge explicite via `/v3/biometric-templates/`. Une session sans utilisateur associé ne peut pas conserver de gabarit (`ineligible_no_vendor_user`). Envoyez `deletion_instruction: privacy_erasure` pour les demandes de personnes concernées : cela purge chaque gabarit conservé pour cet utilisateur et n'en conserve jamais de nouveau.\n\n**Irréversible :** la suppression est définitive et il n'existe aucun endpoint de restauration. Exportez tout ce dont vous avez besoin (par exemple un PDF de décision) avant de l'appeler.\n\n**Effets secondaires :** aucun webhook n'est émis pour les suppressions.\n\n**Réponse :** `200 OK` une fois la suppression terminée, avec un corps JSON indiquant le `face_retention_outcome`, l'expiration du gabarit conservé et, pour une session KYB, `deleted_child_verifications`. Les versions antérieures de cet endpoint renvoyaient `204 No Content` ; mettez à jour les clients qui vérifient `204`. Conservez votre `instruction_id` dans votre propre journal d'effacement.\n\n**Idempotence :** non idempotent au niveau HTTP : le premier appel renvoie `200` ; le répéter renvoie `404` car la session n'est plus résolue. Après un `503`, la session est toujours présente ; réessayez la même requête pour terminer sa suppression.\n\n**Authentification :** envoyez la clé API de votre application dans l'en-tête `x-api-key` ; la session doit appartenir à cette application. Les tokens d'accès utilisateur de la Console (`Authorization: Bearer ...`) peuvent également appeler cet endpoint lorsqu'ils disposent de l'autorisation `delete:sessions`. Les échecs d'authentification et d'autorisation renvoient tous deux `403` ; cette API ne renvoie jamais `401`.\n\n**Limite de débit :** quota d'écriture partagé de 300 requêtes/min par clé API sur l'ensemble des endpoints POST/PATCH/DELETE ; le dépasser renvoie `429`.\n\nPour supprimer en masse des sessions KYC par leur `session_number` numérique, utilisez plutôt `POST /v3/sessions/delete/`.\n\n**Rapports réglementaires déposés :** si les données sélectionnées figurent dans un rapport réglementaire finalisé, l'ensemble de la requête est refusé avec `409` et rien n'est supprimé. Le corps utilise `code: in_filed_report` et nomme chaque rapport avec `uuid`, `report_number`, `report_type` et `case_uuid`. Supprimez les rapports, puis réessayez la requête.",
        "operationId": "delete_v3_session_by_id",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID (`session_id`) de la session de Vérification des utilisateurs (KYC) ou de Vérification d'entreprise (KYB) à supprimer, tel que renvoyé lors de la création de la session. Doit être un UUID canonique avec traits d'union — une valeur qui n'est pas un UUID ne correspond pas à la route et renvoie `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session supprimée. Le corps indique ce qui est advenu des données biométriques faciales de la session et, pour une session KYB, combien de vérifications qu'elle a créées ont été supprimées avec elle.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "La session supprimée."
                    },
                    "session_number": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Le numéro de la session supprimée."
                    },
                    "face_retention_outcome": {
                      "type": "string",
                      "enum": [
                        "retained_with_user",
                        "deleted",
                        "none",
                        "ineligible_no_vendor_user"
                      ],
                      "description": "Ce qui est advenu des données biométriques faciales de la session. `deleted` : l'embedding facial a été supprimé avec la session (par défaut). `retained_with_user` : la session est supprimée et un gabarit biométrique sans image reste rattaché à l'User ; voir `biometric_template_uuid`. `none` : la session ne comportait aucun embedding facial (par exemple une session KYB, ou une session KYC sans selfie de détection du vivant). `ineligible_no_vendor_user` : la conservation a été demandée mais la session n'a aucun User lié, l'embedding a donc été supprimé avec la session. Un échec du stockage biométrique n'est jamais signalé via ce champ sur cet endpoint : il renvoie `503` et la session n'est pas supprimée."
                    },
                    "biometric_template_uuid": {
                      "type": "string",
                      "format": "uuid",
                      "nullable": true,
                      "description": "Identifiant du gabarit biométrique conservé lorsque `face_retention_outcome` vaut `retained_with_user` ; `null` sinon. Gérez-le via `/v3/biometric-templates/{template_uuid}/`."
                    },
                    "biometric_template_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Moment où le gabarit biométrique conservé est supprimé, lorsque `face_retention_outcome` vaut `retained_with_user` ; `null` lorsqu'aucun gabarit n'est conservé."
                    },
                    "deleted_child_verifications": {
                      "type": "integer",
                      "description": "Pour une session de Vérification d'entreprise (KYB) : combien de vérifications créées par celle-ci (les sessions KYC de ses personnes clés et les sessions KYB de ses entités propriétaires, de manière récursive) ont été supprimées avec elle. Vaut toujours `0` pour une session KYC."
                    }
                  }
                },
                "examples": {
                  "Deleted (default)": {
                    "value": {
                      "session_id": "4c5c7f3a-3b1d-4b7e-9c39-2b4f7e6a1d02",
                      "session_number": 1024,
                      "face_retention_outcome": "deleted",
                      "biometric_template_uuid": null,
                      "biometric_template_expires_at": null,
                      "deleted_child_verifications": 0
                    }
                  },
                  "Retained with User": {
                    "value": {
                      "session_id": "4c5c7f3a-3b1d-4b7e-9c39-2b4f7e6a1d02",
                      "session_number": 1024,
                      "face_retention_outcome": "retained_with_user",
                      "biometric_template_uuid": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
                      "biometric_template_expires_at": "2027-10-09T10:15:00Z",
                      "deleted_child_verifications": 0
                    }
                  },
                  "Ineligible: no User": {
                    "summary": "Conservation demandée sur une session créée sans vendor_data",
                    "value": {
                      "session_id": "7a1e9c2d-5f4b-4c3a-8e2d-1b0a9f8e7d6c",
                      "session_number": 1031,
                      "face_retention_outcome": "ineligible_no_vendor_user",
                      "biometric_template_uuid": null,
                      "biometric_template_expires_at": null,
                      "deleted_child_verifications": 0
                    }
                  },
                  "KYB session": {
                    "value": {
                      "session_id": "0f3c9b7e-2d1a-4e5f-8c6b-7a9d8e1f2c3b",
                      "session_number": 88,
                      "face_retention_outcome": "none",
                      "biometric_template_uuid": null,
                      "biometric_template_expires_at": null,
                      "deleted_child_verifications": 3
                    },
                    "summary": "Une vérification d'entreprise supprimée avec les trois vérifications créées pour ses personnes clés"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — rien n'est supprimé.",
            "content": {
              "application/json": {
                "examples": {
                  "Privacy erasure cannot retain": {
                    "value": {
                      "retain_face_embeddings": [
                        "Privacy erasure cannot retain biometric templates."
                      ]
                    }
                  },
                  "No finite retention duration": {
                    "summary": "Conservation demandée sans face_retention_days sur la requête ou l'application",
                    "value": {
                      "detail": "A finite biometric-template retention duration is required."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie également `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Exception : lorsque le `sessionId` ne correspond à aucune session active, la recherche préalable du propriétaire renvoie `404` en premier, même avec des identifiants manquants ou non valides.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête x-api-key, ou la clé est invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Insufficient permission": {
                    "summary": "Token utilisateur sans delete:sessions, ou identifiants pour une application qui ne possède pas la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session KYC ou KYB active avec ce `session_id` n'existe — l'identifiant est inconnu ou la session a déjà été supprimée (répéter une suppression réussie aboutit ici).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not Found": {
                    "summary": "Session inconnue ou déjà supprimée",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit d'écriture partagée dépassée (300 requêtes POST/PATCH/DELETE par minute et par clé API). Examinez `Retry-After` et les en-têtes de réponse `X-RateLimit-*` avant de réessayer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget d'écriture épuisé",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "La suppression n'a pas pu aboutir car un service de stockage, un stockage biométrique ou un fournisseur de surveillance était indisponible. La session est toujours présente ; réessayez la même requête jusqu'à ce qu'elle renvoie `200`. Certains de ses fichiers stockés ou son embedding facial peuvent déjà être supprimés, ne vous y fiez donc pas après un `503`. Les nouvelles tentatives convergent vers un seul modèle.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Session deletion unavailable": {
                    "summary": "Un service de stockage ou un fournisseur de surveillance était indisponible",
                    "value": {
                      "detail": "The session could not be deleted because a storage service or a monitoring provider is unavailable. The session is still in place; repeat the request to finish deleting it."
                    }
                  },
                  "Biometric store unavailable": {
                    "summary": "Un service de stockage biométrique était indisponible lors de la conservation ou de la suppression définitive d'un gabarit",
                    "value": {
                      "detail": "The biometric-template operation could not finish because an external store is unavailable. The operation is retryable."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "La session fait partie d'un rapport réglementaire finalisé. Rien n'est supprimé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InFiledReportError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl (default policy)",
            "source": "curl -X DELETE \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/delete/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "curl",
            "label": "curl (retain template)",
            "source": "curl -X DELETE \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/delete/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"retain_face_embeddings\": true, \"face_retention_days\": 365}'"
          },
          {
            "lang": "curl",
            "label": "curl (privacy erasure)",
            "source": "curl -X DELETE \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/delete/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"deletion_instruction\": \"privacy_erasure\", \"instruction_id\": \"dsar-2026-0142\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n    retain_face_embeddings=True,\n    face_retention_days=365,\n    instruction_id=\"post-approval-cleanup-2026-08\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.delete(\"11111111-2222-3333-4444-555555555555\", {\n  retain_face_embeddings: true,\n  face_retention_days: 365,\n  instruction_id: \"post-approval-cleanup-2026-08\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Delete(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsDeleteParams{\n\tRetainFaceEmbeddings: didit.Bool(true),\n\tFaceRetentionDays:    didit.Int(365),\n\tInstructionID:        didit.String(\"post-approval-cleanup-2026-08\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsDeleteParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().delete(\"11111111-2222-3333-4444-555555555555\", SessionsDeleteParams.builder()\n        .retainFaceEmbeddings(true)\n        .faceRetentionDays(365L)\n        .instructionId(\"post-approval-cleanup-2026-08\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->delete('11111111-2222-3333-4444-555555555555', [\n    'retain_face_embeddings' => true,\n    'face_retention_days' => 365,\n    'instruction_id' => 'post-approval-cleanup-2026-08',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.delete(\n  \"11111111-2222-3333-4444-555555555555\",\n  retain_face_embeddings: true,\n  face_retention_days: 365,\n  instruction_id: \"post-approval-cleanup-2026-08\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.DeleteAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsDeleteParams\n{\n    RetainFaceEmbeddings = true,\n    FaceRetentionDays = 365,\n    InstructionId = \"post-approval-cleanup-2026-08\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Optionnel. Omettez entièrement le corps pour suivre la politique de conservation de l'application avec une suppression opérationnelle.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "retain_face_embeddings": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Remplacer la `face_retention_policy` de l'application pour cette suppression. `true` conserve un gabarit biométrique facial sans image rattaché à l'utilisateur de la session après la suppression de la session ; `false` supprime l'embedding facial avec la session ; omettez ou définissez sur `null` pour suivre la politique de l'application. Ignoré pour les sessions KYB et pour les sessions sans embedding facial.",
                    "example": true
                  },
                  "face_retention_days": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 3650,
                    "description": "Durée de conservation finie, en jours, pour un gabarit conservé. Requise lorsqu'un gabarit est conservé, sauf si l'application définit déjà `face_retention_days`. La valeur `expires_at` du gabarit correspond à la date d'expiration la plus proche, déterminée par cette durée, la fenêtre générale de conservation des données de l'application et `face_retention_deadline`.",
                    "example": 365
                  },
                  "face_retention_deadline": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Expiration stricte optionnelle pour un modèle conservé. Doit être dans le futur.",
                    "example": "2027-08-28T00:00:00Z"
                  },
                  "deletion_instruction": {
                    "type": "string",
                    "enum": [
                      "operational_session_delete",
                      "privacy_erasure"
                    ],
                    "default": "operational_session_delete",
                    "description": "La catégorie d'instruction que vous donnez. `operational_session_delete` supprime la session et ne conserve un modèle que si la politique ou `retain_face_embeddings` l'indique. `privacy_erasure` purge tout gabarit biométrique conservé ancré à l'Utilisateur de la session avant de supprimer la session, ne peut pas être outrepassé par la politique de l'application, et ne peut pas être combiné avec `retain_face_embeddings: true` (`400`).",
                    "example": "operational_session_delete"
                  },
                  "instruction_id": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Votre référence durable pour cette instruction de suppression (par exemple un ID de ticket d'effacement). Enregistrée dans le journal d'audit et sur tout gabarit conservé. Générée par Didit lorsqu'elle est omise.",
                    "example": "dsar-2026-0142"
                  }
                }
              },
              "examples": {
                "Retain a biometric template": {
                  "summary": "Supprimer la session, conserver un modèle sans image pendant 365 jours",
                  "value": {
                    "retain_face_embeddings": true,
                    "face_retention_days": 365,
                    "instruction_id": "post-approval-cleanup-2026-08"
                  }
                },
                "Force deletion on an opted-in application": {
                  "summary": "Supprimer l'embedding facial quelle que soit la politique de l'application",
                  "value": {
                    "retain_face_embeddings": false
                  }
                },
                "Privacy erasure": {
                  "summary": "Demande de la personne concernée : supprimer la session et purger chaque gabarit conservé pour cette personne",
                  "value": {
                    "deletion_instruction": "privacy_erasure",
                    "instruction_id": "dsar-2026-0142"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/session/{sessionId}/generate-pdf/": {
      "get": {
        "summary": "Télécharger un rapport PDF pour une session de vérification",
        "description": "Génère et télécharge un rapport PDF prêt pour la conformité pour une session de vérification terminée. Le même chemin dessert à la fois les sessions de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) — le serveur résout le `sessionId` parmi les deux types de session et sélectionne le modèle de rapport correspondant.\n\n**Statuts éligibles.** La session doit déjà avoir un statut final ou pouvant faire l'objet d'un examen :\n\n- Sessions KYC : `Approved`, `Declined`, `In Review` ou `Kyc Expired`.\n- Sessions KYB : `Approved`, `Declined` ou `In Review`.\n\nTout autre statut (`Not Started`, `In Progress`, `Expired`, `Abandoned`, …) renvoie `403` avec une chaîne explicative `detail` — voir la réponse `403` ci-dessous.\n\n**Contenu du rapport.** Le PDF reflète la vue de la session dans la console au moment de la requête :\n\n- **KYC** — statut global de la session, liste des avertissements et une section par fonctionnalité exécutée : Vérification d'identité (images du document et champs extraits), NFC, Détection du vivant, Correspondance faciale, Vérification de l'e-mail, Vérification du téléphone, Justificatif de domicile, réponses aux Questionnaires, Validation en base de données, Filtrage AML et Analyse IP — suivis des tags de la session, de l'activité d'examen dans la console (commentaires et changements de statut) et de la chronologie des événements de la session.\n- **KYB** — vérifications du registre des sociétés (données de l'entreprise), filtrages AML, vérifications des documents de l'entreprise, vérifications des personnes clés, réponses aux Questionnaires, vérifications du téléphone/de l'e-mail, analyses IP et chronologie des événements de la session, suivis des tags et de l'activité d'examen.\n\n**Image de marque.** Si votre application dispose d'une personnalisation en marque blanche, le rapport est généré avec votre logo et des liens vers l'URL de votre politique de confidentialité ; sinon, il porte la marque Didit. Les rapports sont générés en anglais — il n'y a pas de paramètre de langue.\n\n**Aucune mise en cache.** Chaque appel régénère le PDF à partir des données actuelles de la session, de sorte qu'un rapport généré après un examen manuel reflète la décision du réviseur. Deux appels pour la même session peuvent produire des fichiers différents à l'octet près — archivez le fichier téléchargé si vous avez besoin d'une copie immuable.\n\n**Latence.** La génération télécharge chaque image stockée (recto/verso des documents, selfies, fichiers supplémentaires) avant de composer le PDF, de sorte que les sessions riches en fichiers multimédias peuvent prendre plusieurs secondes. Utilisez un délai d'attente de lecture client généreux (60 s recommandé) et écrivez le corps en flux vers le disque.\n\n**Barre oblique finale.** La route canonique se termine par une barre oblique finale (`…/generate-pdf/`). Une requête sans cette barre oblique est traitée directement avec la même réponse — il n'y a pas de redirection `301`, aucun client n'a donc besoin de suivre les redirections et `curl` ne requiert pas `-L`. Utilisez l'URL avec barre oblique comme dans les exemples.\n\nSi vous avez besoin des données sous-jacentes au format JSON plutôt que d'un rapport généré, utilisez `GET /v3/session/{sessionId}/decision/`. Pour obtenir l'ensemble des sessions d'un utilisateur pouvant faire l'objet d'un rapport dans un seul document, utilisez `GET /v3/users/{vendor_data}/generate-pdf/`.",
        "operationId": "get_v3_session_generate_pdf",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "generate_pdf",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification des utilisateurs (KYC) ou de Vérification d'entreprise (KYB) à générer — le `session_id` renvoyé par `POST /v3/session/`. Le même chemin fonctionne pour les deux types de session ; utilisez le nom de fichier dans `Content-Disposition` sur la réponse pour identifier le type de rapport que vous avez reçu.\n\n**Doit être un UUID bien formé en minuscules.** La route ne correspond qu'aux UUID valides ; par conséquent, une valeur mal formée est rejetée par le routeur d'URL avant même l'exécution du code de l'application, et la réponse est une page **HTML** `404` plutôt que l'enveloppe JSON `{\"detail\": ...}` illustrée ci-dessous. Le convertisseur d'UUID de la route ne correspond qu'à la forme canonique en minuscules — les UUID avec des valeurs hexadécimales en majuscules sont rejetés avec l'erreur HTML 404.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Le document PDF généré, renvoyé directement au format binaire `application/pdf` — il n'y a pas d'encapsulation JSON ni d'indirection par URL de téléchargement. Le corps commence par les octets magiques `%PDF` (PDF 1.7). Enregistrez-le dans un fichier `.pdf` ou transmettez-le à votre appelant sous forme de flux.",
            "headers": {
              "Content-Disposition": {
                "description": "`attachment; filename=session_{sessionId}.pdf` pour les sessions KYC, `attachment; filename=business_{sessionId}.pdf` pour les sessions KYB — le préfixe vous indique quel modèle de rapport a été généré.",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=session_11111111-2222-3333-4444-555555555555.pdf"
                }
              },
              "Content-Length": {
                "description": "Taille totale du PDF en octets ; le corps n'est pas segmenté.",
                "schema": {
                  "type": "integer",
                  "example": 25191
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification, d'autorisation ou de statut de session. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez les différents cas d'échec grâce à la chaîne `detail` :\n\n- `\"Authentication credentials were not provided or are invalid.\"` — aucun en-tête `x-api-key` (et aucun token `Authorization: Bearer`), ou l'identifiant fourni a échoué à l'introspection (révoqué, expiré ou malformé).\n- `\"You do not have permission to perform this action.\"` — l'identifiant est valide mais ne peut pas lire cette session : un token Bearer d'utilisateur de la console ne possède pas l'autorisation `read:sessions` ou ne peut pas accéder à l'application propriétaire, ou une clé API appartient à une organisation différente de celle de la session.\n- `\"You can only generate a PDF for sessions in review, declined, approved or kyc expired\"` — la session KYC existe mais n'a pas encore de statut éligible (par exemple `Not Started` ou `In Progress`). Attendez le webhook `status.updated` avant de demander le rapport.\n- `\"You can only generate a PDF for sessions in review, declined or approved\"` — même condition pour les sessions KYB.\n\nNotez que pour un `sessionId` complètement inconnu, l'endpoint résout l'application propriétaire avant de valider les identifiants ; une session manquante renvoie donc `404` même si les identifiants d'authentification sont manquants ou non valides.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "You can only generate a PDF for sessions in review, declined, approved or kyc expired"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou l'introspection de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Insufficient permissions": {
                    "summary": "Identifiant valide ne disposant pas de read:sessions ou d'un accès à l'application propriétaire",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "KYC session not finished": {
                    "summary": "Session KYC toujours non commencée / en cours",
                    "value": {
                      "detail": "You can only generate a PDF for sessions in review, declined, approved or kyc expired"
                    }
                  },
                  "KYB session not finished": {
                    "summary": "Session KYB toujours non commencée / en cours",
                    "value": {
                      "detail": "You can only generate a PDF for sessions in review, declined or approved"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session active avec ce `sessionId` n'existe — elle n'a jamais été créée ou elle a été supprimée. La résolution du propriétaire intervient avant la validation des identifiants, ce `404` est donc renvoyé même pour les requêtes non authentifiées. Selon la recherche qui échoue, la chaîne `detail` est `\"Not found.\"` (le cas courant) ou `\"Session not found.\"`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Not found."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "summary": "sessionId ne correspond à aucune session KYC ou KYB",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Recently deleted session": {
                    "summary": "La session a été supprimée entre les recherches",
                    "value": {
                      "detail": "Session not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. La génération de PDF fait l'objet d'une limite dédiée de **50 requêtes par minute par identifiant d'authentification** (clé API, token Bearer ou IP source en cas de requête non authentifiée), en plus de la limite globale de 600 GET/min. Attendez le nombre de secondes indiqué par `Retry-After` (également indiqué dans les en-têtes `X-RateLimit-*`), puis réessayez. Les rapports ne sont pas mis en cache côté serveur, téléchargez donc chaque rapport une seule fois et conservez le fichier au lieu de le récupérer à nouveau.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer la requête.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Nombre maximal de générations de PDF autorisées dans la fenêtre actuelle (50).",
                "schema": {
                  "type": "integer",
                  "example": 50
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Horodatage Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1750000000
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Explication lisible par l'humain du dépassement de la limite de débit.",
                      "example": "Session PDF generation rate limit exceeded. You can make up to 50 requests per minute."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "summary": "Plus de 50 générations de PDF en une minute avec le même identifiant",
                    "value": {
                      "detail": "Session PDF generation rate limit exceeded. You can make up to 50 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --fail \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/generate-pdf/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  --output report.pdf"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.sessions.generate_pdf(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nwith open(\"download.pdf\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.sessions.generatePdf(\"11111111-2222-3333-4444-555555555555\");\nawait writeFile(\"download.pdf\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.Sessions.GeneratePDF(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.sessions().generatePdf(\"11111111-2222-3333-4444-555555555555\")\n        .writeTo(Path.of(\"download.pdf\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->sessions->generatePdf('11111111-2222-3333-4444-555555555555');\n$content->saveTo('download.pdf');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.sessions.generate_pdf(\"11111111-2222-3333-4444-555555555555\")\nFile.binwrite(\"download.pdf\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.Sessions.GeneratePdfAsync(\"11111111-2222-3333-4444-555555555555\");\nawait content.SaveToAsync(\"download.pdf\");"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/sandbox/arm/": {
      "post": {
        "summary": "Armer un scénario de sandbox sur une session",
        "description": "Conserver un scénario sandbox sur une session `Not Started` et déployer ses valeurs magiques associées (e-mail, téléphone ou champs `expected_details`) sur la session, afin que les fournisseurs simulés reproduisent le résultat du scénario une fois le flux exécuté. Il s'agit de l'endpoint appelé par le sélecteur de scénario pré-flux dans l'UI de vérification hébergée de Didit lorsqu'un testeur choisit un résultat avant de commencer la capture. Créez votre propre sélecteur avec celui-ci, ou appelez-le directement depuis un banc d'essai sandbox.\n\nAuthentifiez-vous avec le propre `Session-Token` de la session (renvoyé dans `session_token` par [Create Session](/fr/sessions-api/create-session)), et non avec la `x-api-key` de votre application : cet endpoint est conçu pour être appelé depuis le client, pas depuis votre backend. Un scénario n'est accepté que tant que `status` est `Not Started`. L'appeler à nouveau alors qu'il est toujours `Not Started` réarme la session : il applique les valeurs magiques du nouveau scénario et n'efface que les valeurs écrites par le scénario *précédent*, préservant ainsi toute valeur déjà saisie manuellement par l'utilisateur (e-mail, prénom, etc.). Armer une session qui a dépassé l'état `Not Started`, ou qui appartient à une application en production (non sandbox), est rejeté.\n\nConsultez [Sandbox & Test Data](/fr/integration/sandbox-testing) pour le catalogue complet des scénarios et les deux autres manières d'obtenir un résultat : `sandbox_scenario` lors de la création de la session, et la saisie directe de valeurs magiques.",
        "operationId": "post_v3_session_sandbox_arm",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "arm_sandbox",
          "auth": "device_token",
          "server": false
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification sandbox à armer. Doit correspondre à la session encodée dans le Session-Token utilisé pour s'authentifier.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "scenario"
                ],
                "properties": {
                  "scenario": {
                    "type": "string",
                    "description": "Slug du scénario à armer. Consultez le catalogue sur GET /v1/sandbox/scenarios/ ou le tableau des scénarios dans [Sandbox & Données de test](/fr/integration/sandbox-testing).",
                    "example": "decline_document_expired"
                  }
                }
              },
              "examples": {
                "Arm": {
                  "summary": "Armer le scénario de correspondance PEP AML",
                  "value": {
                    "scenario": "decline_aml_hit"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scénario armé. Ses valeurs magiques sont désormais associées à la session. `status` reflète le statut actuel de la session, que cet appel ne modifie jamais : il est toujours `Not Started` en cas de succès.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "scenario": {
                      "type": "string",
                      "description": "Le slug du scénario armé (renvoie la requête)."
                    },
                    "status": {
                      "type": "string",
                      "example": "Not Started"
                    }
                  }
                },
                "examples": {
                  "Armed": {
                    "summary": "Scénario armé sur une session Not Started",
                    "value": {
                      "session_id": "11111111-2222-3333-4444-555555555555",
                      "scenario": "decline_aml_hit",
                      "status": "Not Started"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation : un slug de scénario inconnu, ou la session a déjà progressé au-delà de `Not Started`.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown Scenario": {
                    "summary": "le scénario ne figure pas dans le catalogue",
                    "value": {
                      "scenario": [
                        "Unknown sandbox scenario: 'not-a-real-scenario'."
                      ]
                    }
                  },
                  "Already Started": {
                    "summary": "La session a dépassé le statut Not Started",
                    "value": [
                      "Scenario can only be armed before the verification starts."
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "Le Session-Token ne correspond pas à ce `session_id`, ou la session appartient à une application de production (non sandbox).",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "Session en production, ou non-concordance session_id / token",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/sandbox/arm/ \\\n  -H 'Session-Token: YOUR_SESSION_TOKEN' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"scenario\": \"decline_aml_hit\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import requests\n\nresponse = requests.post(\n    \"https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/sandbox/arm/\",\n    headers={\n        \"Session-Token\": \"YOUR_SESSION_TOKEN\",\n        \"Content-Type\": \"application/json\",\n    },\n    json={\"scenario\": \"decline_aml_hit\"},\n)\nresponse.raise_for_status()\nprint(response.json())  # {'session_id': '...', 'scenario': 'decline_aml_hit', 'status': 'Not Started'}"
          },
          {
            "lang": "javascript",
            "label": "JavaScript",
            "source": "const response = await fetch(\n  'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/sandbox/arm/',\n  {\n    method: 'POST',\n    headers: {\n      'Session-Token': sessionToken,\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({ scenario: 'decline_aml_hit' }),\n  },\n);\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst { session_id, scenario, status } = await response.json();"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/update-status/": {
      "patch": {
        "summary": "Approuver, refuser ou demander une nouvelle soumission pour une session de vérification",
        "description": "Remplacez manuellement la décision finale d'une session de vérification KYC ou KYB. Définissez `new_status` sur `Approved` ou `Declined` pour consigner une décision manuelle, ou sur `Resubmitted` pour effacer des étapes de vérification spécifiques et permettre à l'utilisateur de les refaire via la même URL de vérification. L'endpoint accepte aussi bien les identifiants de session d'utilisateurs (KYC) que d'entreprises (KYB).\n\nAppelez-le dès qu'une session a atteint un état examinable : le statut actuel doit être `Approved`, `Declined`, `In Review`, `Kyc Expired`, `Abandoned` ou `Resubmitted`. Les sessions toujours `Not Started`, `In Progress` ou `Awaiting User`, ou qui se sont terminées par `Expired`, renvoient `400`. Votre clé API doit disposer de l'autorisation `write:sessions` (une clé API restreinte nécessite un accès en écriture aux décisions). La vérification de l'état d'éligibilité s'exécute avant la validation du corps de requête ; une session inéligible renvoie donc l'erreur `Wrong Current Status` même lorsque le payload est également invalide.\n\nPour `Resubmitted`, transmettez `nodes_to_resubmit` pour choisir les étapes du workflow que l'utilisateur doit refaire, ou omettez-le pour sélectionner automatiquement les tentatives existantes des fonctionnalités dans un état pouvant être soumis à nouveau (`Declined`, `In Review`, `Not Finished`, `Expired`). Les fonctionnalités jamais tentées ne sont pas sélectionnées automatiquement : indiquez-les explicitement dans `nodes_to_resubmit`, sinon la requête renvoie `400` lorsqu'aucune tentative enregistrée ne nécessite de nouvelle soumission. Les résultats précédents des étapes sélectionnées sont déplacés vers l'historique de la nouvelle soumission (renvoyé par Get Decision avec `include=resubmissions`), les étapes sont réordonnées pour correspondre au graphe du workflow, la fenêtre d'expiration de la session redémarre et l'URL de vérification d'origine redevient utilisable. Les étapes exécutées uniquement côté backend (`AML`, `DATABASE_VALIDATION`, `IP_ANALYSIS`) en tête de liste s'exécutent immédiatement sans intervention de l'utilisateur ; si toutes les étapes soumises à nouveau sont uniquement côté backend, la session est finalisée à nouveau au sein de la même requête. `KYB_REGISTRY` et `KYB_KEY_PEOPLE` ne peuvent pas être soumis à nouveau directement : soumettez plutôt à nouveau les sessions KYC enfants concernées, et la session d'entreprise parente est recalculée automatiquement.\n\nChaque appel modifiant le statut déclenche le [webhook](/fr/integration/webhooks) `status.updated` une fois la modification validée et ajoute une entrée d'activité (avec attribution de l'intervenant et votre `comment`) aux `reviews` de la session, visible dans [Get Decision](#get-/v3/session/-sessionId-/decision/) et dans la chronologie d'activité de la console. Les agrégats de profil utilisateur associés aux `vendor_data` de la session sont également mis à jour. Un refus désactive la surveillance AML continue pour la session ; une nouvelle approbation la réactive (depuis `Resubmitted`, `Declined` ou `Kyc Expired`) lorsque la surveillance est activée dans le workflow. Approuver ou refuser un KYC enfant faisant partie d'une vérification des personnes clés d'un KYB recalcule le statut de la session d'entreprise parente. Définissez `send_email: true` (avec `email_address`) pour avertir l'utilisateur : un avis de statut pour `Approved`/`Declined`, ou un e-mail de nouvelle soumission contenant le lien de vérification et les motifs par étape pour `Resubmitted`. Pour vérifier l'e-mail au préalable, prévisualisez-le avec [Preview Decision Email](/fr/sessions-api/preview-decision-email) (`Approved`, `Declined`) ou [Preview Resubmission Email](/fr/sessions-api/preview-resubmission) (`Resubmitted`) et transmettez son `preview_token` dans `email_preview_token` : la mise à jour envoie alors exactement l'e-mail prévisualisé, ou renvoie `409` avant toute modification si l'e-mail ou la session a changé depuis la prévisualisation ou si le reçu date de plus de 15 minutes.\n\nRépéter `Approved` ou `Declined` sur une session ayant déjà ce statut ne modifie rien et renvoie `200` : aucun webhook, aucune entrée d'activité et aucun e-mail. Répéter `Resubmitted` renvoie `400` (`The new status is the same as the current status.`). Des identifiants manquants ou invalides et des autorisations manquantes renvoient `403` ; une clé API restreinte expirée renvoie `401`.",
        "operationId": "patch_v3_session_update_status",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_status",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification à mettre à jour. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB) — le service résout l'identifiant pour les deux types de session.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "new_status"
                ],
                "properties": {
                  "new_status": {
                    "type": "string",
                    "description": "Statut cible. `Approved` et `Declined` enregistrent une décision manuelle définitive (chacun pouvant également annuler l'autre). `Resubmitted` efface les étapes sélectionnées et renvoie la session à l'utilisateur. Toute autre valeur renvoie `400`.",
                    "enum": [
                      "Approved",
                      "Declined",
                      "Resubmitted"
                    ],
                    "example": "Approved"
                  },
                  "comment": {
                    "type": "string",
                    "description": "Motif en texte libre du changement, stocké dans l'historique d'examen de la session et renvoyé dans le tableau `reviews` de [Get Decision](#get-/v3/session/-sessionId-/decision/). Par exemple `Duplicated user`.",
                    "example": "All checks passed manual review"
                  },
                  "nodes_to_resubmit": {
                    "type": "array",
                    "description": "Étapes du workflow que l'utilisateur doit recommencer. Prises en compte uniquement lorsque `new_status` est `Resubmitted`. Pour `Approved`/`Declined`, les entrées font toujours l'objet d'une validation de schéma (une valeur `feature` non valide renvoie `400`), mais les entrées valides selon le schéma sont sémantiquement ignorées. En cas d'omission, le serveur sélectionne automatiquement les tentatives existantes d'OCR, de détection du vivant, de correspondance faciale, de justificatif de domicile, de téléphone, d'e-mail, d'AML, de validation en base de données et de questionnaire dont le statut est `Declined`, `In Review`, `Not Finished` ou `Expired` (les tentatives de NFC, d'analyse de l'IP, d'estimation de l'âge, de recherche faciale et de documents KYB ne sont jamais sélectionnées automatiquement ; les tentatives faciales hors correspondance faciale sont sélectionnées en tant que `LIVENESS`) — les fonctionnalités que l'utilisateur n'a jamais tentées (aucune tentative enregistrée) ne sont PAS sélectionnées, de sorte qu'une session avec zéro tentative renvoie `400` (« No features found that need resubmission ») même si rien n'a été approuvé ; transmettez explicitement `nodes_to_resubmit` dans ce cas. Les étapes sont exécutées dans l'ordre du graphe du workflow, quel que soit l'ordre dans lequel vous les envoyez. `KYB_REGISTRY`, `KYB_KEY_PEOPLE` et l'alias `KYB` sont rejetés avec un code `400` — ces vérifications parentes sont recalculées à partir de leurs sessions KYC enfants.",
                    "items": {
                      "type": "object",
                      "required": [
                        "node_id",
                        "feature"
                      ],
                      "properties": {
                        "node_id": {
                          "type": "string",
                          "description": "Identifiant du nœud tel qu'il apparaît dans la définition du workflow de la session (par exemple `feature_ocr`, `feature_liveness`).",
                          "example": "feature_ocr"
                        },
                        "feature": {
                          "type": "string",
                          "description": "Type de fonctionnalité du nœud. Les alias `ID_VERIFICATION`, `POA`, `PHONE` et `EMAIL` sont normalisés côté serveur en `OCR`, `PROOF_OF_ADDRESS`, `PHONE_VERIFICATION` et `EMAIL_VERIFICATION`. `KYB_REGISTRY`, `KYB_KEY_PEOPLE` et `KYB` passent la validation du schéma mais sont toujours rejetés avec l'erreur de règle métier `400` montrée dans les exemples.",
                          "enum": [
                            "OCR",
                            "OCR_BACK",
                            "NFC",
                            "AML",
                            "FACE",
                            "LIVENESS",
                            "FACE_MATCH",
                            "IP_ANALYSIS",
                            "AGE_ESTIMATION",
                            "PROOF_OF_ADDRESS",
                            "PHONE_VERIFICATION",
                            "EMAIL_VERIFICATION",
                            "FACE_SEARCH",
                            "DATABASE_VALIDATION",
                            "QUESTIONNAIRE",
                            "DOCUMENT_AI",
                            "KYB_DOCUMENTS",
                            "ID_VERIFICATION",
                            "POA",
                            "PHONE",
                            "EMAIL",
                            "KYB_REGISTRY",
                            "KYB_KEY_PEOPLE",
                            "KYB",
                            "GEOLOCATION"
                          ],
                          "example": "OCR"
                        }
                      }
                    }
                  },
                  "send_email": {
                    "type": "boolean",
                    "description": "Indique s'il faut envoyer un e-mail à l'utilisateur concernant le changement. Nécessite `email_address`. Pour `Approved`/`Declined`, l'utilisateur reçoit une notification de statut ; pour `Resubmitted`, l'e-mail comprend le lien de vérification et les motifs de resoumission par étape.",
                    "default": false,
                    "example": false
                  },
                  "email_address": {
                    "type": "string",
                    "format": "email",
                    "description": "Destinataire de l'e-mail de notification. **Requis lorsque `send_email` est `true`** — l'omettre renvoie `400`.",
                    "example": "user@example.com"
                  },
                  "email_language": {
                    "type": "string",
                    "description": "Langue de l'e-mail de notification. Accepte n'importe quelle chaîne au niveau du schéma ; les codes non pris en charge basculent silencieusement sur l'anglais (`en`).",
                    "default": "en",
                    "example": "en"
                  },
                  "email_preview_token": {
                    "type": "string",
                    "writeOnly": true,
                    "minLength": 1,
                    "maxLength": 512,
                    "description": "Reçu optionnel issu de [Preview Decision Email](/fr/sessions-api/preview-decision-email) (pour `Approved` et `Declined`) ou de [Preview Resubmission Email](/fr/sessions-api/preview-resubmission) (pour `Resubmitted`) : son `preview_token`. Valide uniquement avec `send_email: true` ; sans cela, la requête renvoie `400`. Le destinataire, la langue, le statut de la session, l'expéditeur et l'e-mail (et, pour une nouvelle soumission, les étapes sélectionnées) doivent toujours correspondre à l'aperçu, et le reçu expire après 15 minutes. Dans le cas contraire, la requête renvoie `409` avant que la session ne soit modifiée ou qu'un e-mail ne soit envoyé. Les intégrations existantes peuvent omettre ce champ."
                  }
                }
              },
              "examples": {
                "Approve Session": {
                  "summary": "Approuver une session après examen manuel",
                  "value": {
                    "new_status": "Approved",
                    "comment": "All checks passed manual review"
                  }
                },
                "Decline Session": {
                  "summary": "Refuser une session",
                  "value": {
                    "new_status": "Declined",
                    "comment": "Suspected fraud"
                  }
                },
                "Resubmit Specific Steps": {
                  "summary": "Demander une nouvelle soumission pour les étapes choisies, par e-mail",
                  "value": {
                    "new_status": "Resubmitted",
                    "nodes_to_resubmit": [
                      {
                        "node_id": "feature_ocr",
                        "feature": "OCR"
                      },
                      {
                        "node_id": "feature_liveness",
                        "feature": "LIVENESS"
                      }
                    ],
                    "send_email": true,
                    "email_address": "user@example.com",
                    "email_language": "en"
                  }
                },
                "Resubmit Auto-select": {
                  "summary": "Demander une nouvelle soumission (sélectionne automatiquement les étapes non approuvées)",
                  "value": {
                    "new_status": "Resubmitted"
                  }
                },
                "Approve With Previewed Email": {
                  "summary": "Approuver et envoyer l'e-mail renvoyé par Preview Decision Email",
                  "value": {
                    "new_status": "Approved",
                    "send_email": true,
                    "email_address": "person@example.com",
                    "email_language": "en",
                    "email_preview_token": "eyJkaWdlc3QiOiI0ZjJhIn0:1uExAm:Pl3x4mpleS1gnatureValue000000000000000"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Statut mis à jour. La réponse contient uniquement le `session_id` ; récupérez la session mise à jour via [Get Decision](#get-/v3/session/-sessionId-/decision/). Le webhook `status.updated` se déclenche dès que la modification est enregistrée. Répéter `Approved` ou `Declined` renvoie le même corps et ne modifie rien.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "UUID de la session mise à jour."
                    }
                  }
                },
                "examples": {
                  "Updated": {
                    "summary": "Renvoyé indifféremment pour Approuvé, Refusé et Resoumis",
                    "value": {
                      "session_id": "3472fb7c-8f7c-4d1a-9cf4-cf3d74ce1a60"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les erreurs de champ sont renvoyées sous la forme `{\"<field>\": [\"<message>\"]}` (certains refus liés aux règles métier utilisent plutôt une chaîne : `{\"nodes_to_resubmit\": \"<message>\"}`), les erreurs de transition d'état sous la forme `{\"detail\": \"<message>\"}`, et l'erreur d'état identique sous la forme d'un tableau JSON simple.",
            "content": {
              "application/json": {
                "examples": {
                  "Wrong Current Status": {
                    "summary": "La session n'est pas dans un état modifiable",
                    "value": {
                      "detail": "Only sessions with status Approved, Declined, In Review, Kyc Expired, Abandoned, Resubmitted can be updated. Current status: In Progress"
                    }
                  },
                  "Invalid Status Value": {
                    "summary": "new_status est un statut de session réel mais ne fait pas partie de Approved/Declined/Resubmitted",
                    "value": {
                      "new_status": [
                        "You can only update the status to 'Approved', 'Declined', or 'Resubmitted'."
                      ]
                    }
                  },
                  "Missing new_status": {
                    "summary": "Champ obligatoire omis",
                    "value": {
                      "new_status": [
                        "This field is required."
                      ]
                    }
                  },
                  "Same Status": {
                    "summary": "Resoumission demandée sur une session qui est déjà resoumise",
                    "value": [
                      "The new status is the same as the current status."
                    ]
                  },
                  "Email Address Required": {
                    "summary": "send_email true sans email_address",
                    "value": {
                      "email_address": [
                        "Email address is required when send_email is true."
                      ]
                    }
                  },
                  "Non-resubmittable Feature": {
                    "summary": "La resoumission cible une vérification parente KYB",
                    "value": {
                      "nodes_to_resubmit": "The following features cannot be resubmitted directly: KYB_REGISTRY. Resubmit the relevant child KYC sessions instead; the parent will recompute automatically."
                    }
                  },
                  "Nothing To Resubmit": {
                    "summary": "La sélection automatique n'a trouvé aucune fonctionnalité non approuvée",
                    "value": {
                      "nodes_to_resubmit": "No features found that need resubmission. All features are already approved."
                    }
                  },
                  "Invalid Feature Choice": {
                    "summary": "Fonctionnalité inconnue dans nodes_to_resubmit",
                    "value": {
                      "nodes_to_resubmit": [
                        {
                          "feature": [
                            "\"BOGUS\" is not a valid choice. Valid choices are: OCR, OCR_BACK, NFC, AML, FACE, LIVENESS, FACE_MATCH, IP_ANALYSIS, AGE_ESTIMATION, PROOF_OF_ADDRESS, PHONE_VERIFICATION, EMAIL_VERIFICATION, FACE_SEARCH, DATABASE_VALIDATION, QUESTIONNAIRE, KYB_REGISTRY, KYB_DOCUMENTS, KYB_KEY_PEOPLE, ID_VERIFICATION, POA, PHONE, EMAIL, KYB"
                          ]
                        }
                      ]
                    }
                  },
                  "Invalid Status Value (not a status at all)": {
                    "summary": "new_status n'est pas une valeur StatusChoices valide",
                    "value": {
                      "new_status": [
                        "\"Bogus\" is not a valid choice."
                      ]
                    }
                  },
                  "Preview Receipt Without Email": {
                    "summary": "email_preview_token envoyé sans send_email: true",
                    "value": {
                      "email_preview_token": [
                        "A preview receipt is only valid when the email is sent."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API Key": {
                    "summary": "Clé API restreinte ayant dépassé sa date d'expiration",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants ou autorisations insuffisantes, ou un `session_id` qui appartient à une autre application.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "La clé API ne dispose pas de l'autorisation write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session KYC ou KYB avec ce `session_id` n'existe (les sessions supprimées renvoient également `404`).",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "session_id inconnu",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Une nouvelle soumission ciblant uniquement des fonctionnalités exclusivement backend (AML, DATABASE_VALIDATION, IP_ANALYSIS) a été répétée pendant la période de temporisation de 30 secondes ; une répétition immédiate ne peut pas modifier le résultat. Réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Backend-only resubmit throttled": {
                    "value": {
                      "detail": "This session was already resubmitted for backend-only features within the last 30 seconds; repeating it cannot change the outcome. Wait before resubmitting again."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "L'aperçu de l'e-mail a changé ou a expiré. Générez un nouvel aperçu avant de confirmer ; aucune modification de session ni livraison d'e-mail n'a lieu.",
            "content": {
              "application/json": {
                "examples": {
                  "Preview Changed": {
                    "summary": "Le reçu ne correspond plus ou a plus de 15 minutes",
                    "value": {
                      "detail": "This email preview changed or expired. Preview the message again before confirming."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/update-status/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"new_status\": \"Approved\",\n    \"comment\": \"All checks passed manual review\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_status(\n    \"11111111-2222-3333-4444-555555555555\",\n    new_status=\"Approved\",\n    comment=\"All checks passed manual review\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateStatus(\"11111111-2222-3333-4444-555555555555\", {\n  new_status: \"Approved\",\n  comment: \"All checks passed manual review\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateStatus(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsUpdateStatusParams{\n\tNewStatus: \"Approved\",\n\tComment:   didit.String(\"All checks passed manual review\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsUpdateStatusParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateStatus(\"11111111-2222-3333-4444-555555555555\", SessionsUpdateStatusParams.builder()\n        .newStatus(SessionsUpdateStatusParams.NewStatus.of(\"Approved\"))\n        .comment(\"All checks passed manual review\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateStatus('11111111-2222-3333-4444-555555555555', [\n    'new_status' => 'Approved',\n    'comment' => 'All checks passed manual review',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_status(\n  \"11111111-2222-3333-4444-555555555555\",\n  new_status: \"Approved\",\n  comment: \"All checks passed manual review\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateStatusAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsUpdateStatusParams\n{\n    NewStatus = \"Approved\",\n    Comment = \"All checks passed manual review\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/id-verification/": {
      "post": {
        "summary": "Vérification d'identité (OCR du document + contrôles de fraude)",
        "description": "Effectuez l'OCR d'un document d'identité et exécutez des vérifications de fraude documentaire en un seul appel : renvoie les champs extraits du titulaire, la MRZ analysée, un `status` valant `Approved`/`Declined`/`In Review`, ainsi qu'une liste `warnings` expliquant chaque problème détecté. Prend en charge 14,000+ types de documents provenant de 220+ pays et territoires.\n\n**Fonctionnement.** Envoyez le `front_image` (requis) du document et, pour les documents recto verso, le `back_image`. Téléversez des photos non rognées avec les quatre coins du document visibles : le service détecte, aligne et rogne le document lui-même, ne le pré-rognez donc pas. Le document est classifié automatiquement (vous ne déclarez jamais le pays ni le type de document), la zone visuelle est lue par OCR, et la MRZ ainsi que les éventuels codes-barres sont décodés. Des vérifications croisées valident ensuite les dates, les formats de numéros et les chiffres de contrôle de la MRZ, et comparent la zone visuelle à la MRZ. Avec `perform_document_liveness=true`, les images sont en outre analysées pour détecter les rediffusions d'écran, les copies imprimées et les manipulations du portrait.\n\n**Logique de décision.** Le `status` est `Approved` sauf si au moins un avertissement entraîne un refus. Les risques de fraude et les échecs bloquants entraînent toujours un refus : `DOCUMENT_EXPIRED`, `SCREEN_CAPTURE_DETECTED`, `PRINTED_COPY_DETECTED`, `PORTRAIT_MANIPULATION_DETECTED`, `PUBLIC_DOCUMENT_IMAGE_DETECTED`, ainsi que les échecs d'extraction (`NAME_NOT_DETECTED`, `DATE_OF_BIRTH_NOT_DETECTED`, `DOCUMENT_NUMBER_NOT_DETECTED`). (`PORTRAIT_IMAGE_NOT_DETECTED`, `INVALID_DATE` et `MRZ_NOT_DETECTED` existent dans les sessions de workflow mais ne sont jamais générés par cet endpoint autonome. `COULD_NOT_DETECT_DOCUMENT_TYPE` est renvoyé ici lorsque l'image recto ne correspond pas à un modèle de document officiel connu avec un degré de confiance élevé, et refuse la requête.) Trois groupes de risques sont configurables par requête via `invalid_mrz_action`, `inconsistent_data_action` et `expiration_date_not_detected_action` (`DECLINE` ou `NO_ACTION`). Tous les autres avertissements (par exemple `POSSIBLE_DUPLICATED_USER`) sont informatifs et n'entraînent jamais de refus par eux-mêmes. Lorsque `perform_document_liveness=true` (la valeur par défaut) et que le contrôle de contrefaçon ne renvoie aucun score exploitable — le fournisseur a échoué, a répondu par un code non-200 ou par un HTTP 200 avec `status=\"ERR\"` — l'appel renvoie `200` avec `status: \"In Review\"` et un avertissement `DOCUMENT_LIVENESS_NOT_COMPUTED` (`log_type: \"warning\"`) au lieu de `Approved` : un contrôle qui n'a pas été exécuté ne constitue pas une preuve de l'authenticité du document. Cette escalade n'est pas configurable et ne prévaut jamais sur un `Declined` ; avec `perform_document_liveness=false`, le contrôle est ignoré et le statut suit les avertissements restants comme auparavant. Un document qui ne peut pas du tout être traité renvoie `400` avec `{\"error\": \"COULD_NOT_RECOGNIZE_DOCUMENT\"}` ; un document lisible mais problématique renvoie `200` avec `status: \"Declined\"` : inspectez toujours `id_verification.status` et `id_verification.warnings`, et pas seulement le code HTTP.\n\n**Facturation.** Chaque réponse `200` consomme un crédit d'API Vérification d'identité (décompté de vos crédits de forfait ou de votre solde de recharge). Lorsque le solde de l'organisation ne permet pas de couvrir l'appel, l'endpoint renvoie `403` avec l'erreur de crédits insuffisants avant tout traitement d'image.\n\n**Persistance de la session (`save_api_request`, par défaut `true`).** Lorsqu'il vaut `true`, l'appel est conservé sous forme de session de type API : il apparaît dans la Business Console, le `request_id` renvoyé est un véritable identifiant de session que vous pouvez transmettre à `GET /v3/session/{sessionId}/decision/`, les images rognées du document et du portrait sont stockées et renvoyées sous forme d'URL de médias éphémères (`https://<media-host>/ocr/...`), et un webhook `status.updated` est émis vers vos endpoints de webhook configurés. Lorsqu'il vaut `false`, rien n'est stocké, `request_id` est un UUID de corrélation à usage unique, et `portrait_image`/`front_image`/`back_image` sont renvoyés directement sous forme de chaînes JPEG encodées en base64.\n\n**Sandbox.** Les clés API sandbox ignorent l'ensemble des traitements et de la facturation : après validation de la requête (une entrée malformée renvoie toujours `400`), l'endpoint renvoie un payload fictif statique `Approved` (une carte d'identité américaine fictive « Sandbox User »), aucune session n'est conservée et aucun crédit n'est consommé.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou invalides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) : cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes/min par clé API sur tous les endpoints POST/PATCH/DELETE ; tout dépassement renvoie `429`.",
        "operationId": "post_v3id-verification",
        "x-didit-sdk": {
          "resource": "id_verification",
          "method": "verify",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "front_image"
                ],
                "properties": {
                  "front_image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Recto du document d'identité. Extensions autorisées : `tiff`, `jpg`, `jpeg`, `png`, `webp`, `pdf`. Taille maximale de téléversement : **10 MB** (les fichiers plus volumineux sont rejetés avec une erreur `400`). Les PDF sont convertis en image avant l'OCR ; les PDF chiffrés nécessitent `front_image_password`. Les images sont automatiquement compressées à ~0.5 MB et l'orientation EXIF est appliquée. Téléversez la capture complète, non recadrée, avec les quatre coins du document visibles."
                  },
                  "front_image_password": {
                    "type": "string",
                    "description": "Mot de passe pour déchiffrer `front_image` lorsqu'il s'agit d'un PDF chiffré. L'envoi d'un PDF chiffré sans mot de passe (ou avec un mot de passe incorrect) renvoie `400`.",
                    "writeOnly": true
                  },
                  "back_image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Verso du document — envoyez-le chaque fois que le document en comporte un (de nombreuses cartes d'identité portent la MRZ ou un code-barres au verso ; l'omettre laisse simplement les champs de la MRZ et du verso vides dans la réponse — cet endpoint ne déclenche pas d'avertissement pour MRZ manquante). Mêmes formats et limites de taille que pour `front_image`. S'il est omis, `back_image` et les champs du verso sont `null` dans la réponse."
                  },
                  "back_image_password": {
                    "type": "string",
                    "description": "Mot de passe pour déchiffrer `back_image` lorsqu'il s'agit d'un PDF chiffré.",
                    "writeOnly": true
                  },
                  "perform_document_liveness": {
                    "type": "boolean",
                    "default": true,
                    "description": "Analyse les deux images à la recherche de fraude par présentation : rediffusions d'écran (`SCREEN_CAPTURE_DETECTED`), copies imprimées (`PRINTED_COPY_DETECTED`) et manipulation de portrait (`PORTRAIT_MANIPULATION_DETECTED`). L'un quelconque de ces éléments entraîne un refus automatique. Activé par défaut ; définissez sur `false` pour ignorer le filtrage de fraude et réduire la latence. Lorsqu'il est activé et que le fournisseur ne renvoie aucun score exploitable, la réponse est `In Review` avec un avertissement `DOCUMENT_LIVENESS_NOT_COMPUTED` plutôt que `Approved`.",
                    "example": true
                  },
                  "minimum_age": {
                    "type": "integer",
                    "nullable": true,
                    "default": null,
                    "minimum": 1,
                    "maximum": 120,
                    "description": "Accepté et validé (1–120) mais **actuellement non appliqué** par cet endpoint — il ne génère jamais d'avertissement `MINIMUM_AGE_NOT_MET` à partir de ce champ. Appliquez les règles d'âge à partir de `date_of_birth`/`age` renvoyés, ou utilisez un workflow de session de vérification avec des restrictions d'âge."
                  },
                  "expiration_date_not_detected_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Ce qu'il faut faire lorsqu'aucune date d'expiration ne peut être lue (`EXPIRATION_DATE_NOT_DETECTED`). Par défaut `NO_ACTION`, car de nombreux documents d'identité n'affichent pas de date d'expiration. Remarque : une date d'expiration *détectée et dépassée* entraîne toujours un refus (`DOCUMENT_EXPIRED`), quelle que soit cette option."
                  },
                  "invalid_mrz_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "DECLINE",
                    "description": "Que faire lorsque la MRZ extraite échoue à la validation de la clé de contrôle (`MRZ_VALIDATION_FAILED`). Une MRZ manquante ne génère aucun avertissement sur cet endpoint. Pertinent uniquement pour les documents comportant une MRZ. `REVIEW` n'est pas pris en charge sur cet endpoint et renvoie `400`."
                  },
                  "inconsistent_data_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "DECLINE",
                    "description": "Ce qu'il faut faire lorsque les données extraites sont incohérentes en interne : `DATA_INCONSISTENT`, `MRZ_AND_DATA_EXTRACTED_FROM_OCR_NOT_SAME` (la zone visuelle ne concorde pas avec la MRZ), ou `DOCUMENT_NAME_DIFFERENT_FROM_OTHER_APPROVED_DOCUMENTS`."
                  },
                  "critical_field_occlusion_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "DECLINE",
                    "description": "Ce qu'il faut faire lorsqu'un champ imprimé critique a été physiquement masqué sur la capture (`CRITICAL_FIELD_OCCLUSION_DETECTED`) - un numéro d'identité, un nom, la date de naissance ou la date d'expiration. Entraîne un refus par défaut, comme les autres risques d'intégrité documentaire de cet endpoint : masquer les numéros sur lesquels un rapport est réconcilié correspond à ce à quoi ressemble un document caviardé. La valeur lue pour un champ masqué est supprimée de l'extraction dans tous les cas, de sorte que l'avertissement `*_NOT_DETECTED` correspondant l'accompagne généralement. `REVIEW` n'est pas pris en charge sur cet endpoint et renvoie `400`."
                  },
                  "document_or_personal_number_format_mismatch_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Ce qu'il faut faire lorsqu'un numéro ne correspond pas au format utilisé par son autorité émettrice pour ce type de document (`DOCUMENT_NUMBER_FORMAT_MISMATCH`, `PERSONAL_NUMBER_FORMAT_MISMATCH`). Par défaut `NO_ACTION`, ce qui signale l'avertissement sans modifier le statut. `REVIEW` n'est pas pris en charge sur cet endpoint et renvoie `400`."
                  },
                  "preferred_characters": {
                    "type": "string",
                    "enum": [
                      "latin",
                      "non_latin"
                    ],
                    "default": "latin",
                    "description": "Système d'écriture préféré pour les champs de nom/adresse sur les documents comportant à la fois du texte latin et non latin (arabe, cyrillique, CJK, …). `latin` renvoie des valeurs translittérées/latines ; `non_latin` privilégie le système d'écriture natif."
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Lorsque la valeur est `true` (par défaut), conserve l'appel sous la forme d'une session de type API — visible dans la Business Console, récupérable via `GET /v3/session/{sessionId}/decision/` à l'aide du `request_id` renvoyé, notifiée via un webhook `status.updated`, et avec les images du document renvoyées sous forme d'URL de médias. Lorsque la valeur est `false`, rien n'est stocké, `request_id` est un UUID éphémère et les images sont renvoyées en ligne sous forme de chaînes JPEG en base64.",
                    "example": true
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Chaîne opaque optionnelle (votre identifiant d'utilisateur interne, e-mail, UUID…) stockée sur la session persistée et renvoyée dans la réponse. Utilisez-la pour corréler les appels d'API avec vos propres enregistrements et pour filtrer les sessions ultérieurement.",
                    "example": "user-123"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Objet JSON optionnel stocké avec la session (lorsque `save_api_request=true`) et renvoyé dans la réponse. Dans les requêtes multipart, envoyez-le sous forme de champ textuel encodé en JSON (par ex. `metadata={\"flow\":\"onboarding\"}`) — il est analysé sous forme d'objet.",
                    "example": {
                      "flow": "onboarding"
                    }
                  }
                }
              },
              "example": {
                "front_image": "(binary JPEG/PNG/PDF of the document front)",
                "back_image": "(binary JPEG/PNG/PDF of the document back)",
                "perform_document_liveness": true,
                "save_api_request": true,
                "vendor_data": "user-123",
                "metadata": {
                  "flow": "onboarding"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document traité. `id_verification.status` est `Approved`, `Declined` ou `In Review` ; chaque problème détecté est détaillé dans `id_verification.warnings`. `In Review` est renvoyé lorsqu'une vérification demandée de détection du vivant du document n'a produit aucun résultat exploitable (`DOCUMENT_LIVENESS_NOT_COMPUTED`). Un document problématique renvoie tout de même `200` avec `status: \"Declined\"` — inspectez le corps de la réponse, pas seulement le code HTTP. Lorsque `save_api_request=true`, `request_id` est l'identifiant de la session enregistrée et les champs d'image sont des URL de médias de courte durée ; avec `save_api_request=false`, ce sont des chaînes JPEG en base64 intégrées.",
            "content": {
              "application/json": {
                "examples": {
                  "Approved": {
                    "summary": "Carte d'identité recto verso lue correctement (enregistrée — images sous forme d'URL de médias)",
                    "value": {
                      "request_id": "11d219ed-d59c-4b1d-8d65-9b933f12d5b8",
                      "id_verification": {
                        "status": "Approved",
                        "document_type": "Identity Card",
                        "document_subtype": "ID_CARD_GENERIC",
                        "document_number": "CBX164224",
                        "personal_number": "20446581H",
                        "portrait_image": "https://<media-host>/ocr/11d219ed-d59c-4b1d-8d65-9b933f12d5b8-portrait_image-8c2f.jpg?signature=...",
                        "front_image": "https://<media-host>/ocr/11d219ed-d59c-4b1d-8d65-9b933f12d5b8-front_image-4a1e.jpg?signature=...",
                        "back_image": "https://<media-host>/ocr/11d219ed-d59c-4b1d-8d65-9b933f12d5b8-back_image-77b0.jpg?signature=...",
                        "front_image_camera_front": null,
                        "back_image_camera_front": null,
                        "front_image_camera_front_face_match_score": null,
                        "back_image_camera_front_face_match_score": null,
                        "front_image_quality_score": {
                          "focus_score": 78.0,
                          "brightness_score": 83.2,
                          "brightness_issue": "ok",
                          "is_document_fully_visible": true,
                          "resolution_score": 40.7,
                          "overall_score": 70.2
                        },
                        "back_image_quality_score": {
                          "focus_score": 100.0,
                          "brightness_score": 95.6,
                          "brightness_issue": "ok",
                          "is_document_fully_visible": true,
                          "resolution_score": 43.0,
                          "overall_score": 84.4
                        },
                        "date_of_birth": "1980-01-13",
                        "age": 46,
                        "expiration_date": "2032-03-31",
                        "date_of_issue": "2022-03-31",
                        "issuing_state": "ESP",
                        "issuing_state_name": "Spain",
                        "first_name": "Julio Francisco",
                        "last_name": "Fores Sena",
                        "full_name": "Julio Francisco Fores Sena",
                        "gender": "M",
                        "address": "Brda. Urb. El Cardonal 0052 52 Po3 B,Taco,San Cristobal De La Laguna,Santa Cruz De Tenerife",
                        "formatted_address": "Av. el Cardonal, 52, b, 38108 La Laguna, Santa Cruz de Tenerife, Spain",
                        "place_of_birth": "Valencia, Valencia",
                        "marital_status": "UNKNOWN",
                        "nationality": "ESP",
                        "extra_fields": {
                          "first_surname": "Fores",
                          "second_surname": "Sena"
                        },
                        "mrz": {
                          "surname": "FORES SENA",
                          "name": "JULIO FRANCISCO",
                          "country": "ESP",
                          "nationality": "ESP",
                          "birth_date": "800113",
                          "expiry_date": "320331",
                          "sex": "M",
                          "document_type": "ID",
                          "document_number": "CBX164224",
                          "optional_data": "20446581H",
                          "optional_data_2": "",
                          "birth_date_hash": "9",
                          "expiry_date_hash": "8",
                          "document_number_hash": "3",
                          "final_hash": "3",
                          "personal_number": "20446581H",
                          "warnings": [],
                          "errors": [],
                          "mrz_type": "TD1",
                          "mrz_string": "IDESPCBX164224320446581H<<<<<<\n8001139M3203318ESP<<<<<<<<<<<3\nFORES<SENA<<JULIO<FRANCISCO<<<",
                          "mrz_key": "CBX164224380011393203318"
                        },
                        "parsed_address": {
                          "street_1": "Avenida el Cardonal 52",
                          "street_2": "b",
                          "city": "La Laguna",
                          "region": "Canarias",
                          "country": "ES",
                          "postal_code": "38108",
                          "address_type": "Avenida",
                          "formatted_address": "Av. el Cardonal, 52, b, 38108 La Laguna, Santa Cruz de Tenerife, Spain",
                          "raw_results": {
                            "address_components": [
                              {
                                "long_name": "b",
                                "short_name": "b",
                                "types": [
                                  "subpremise"
                                ]
                              },
                              {
                                "long_name": "52",
                                "short_name": "52",
                                "types": [
                                  "street_number"
                                ]
                              },
                              {
                                "long_name": "Avenida el Cardonal",
                                "short_name": "Av. el Cardonal",
                                "types": [
                                  "route"
                                ]
                              },
                              {
                                "long_name": "La Laguna",
                                "short_name": "La Laguna",
                                "types": [
                                  "locality",
                                  "political"
                                ]
                              },
                              {
                                "long_name": "Spain",
                                "short_name": "ES",
                                "types": [
                                  "country",
                                  "political"
                                ]
                              },
                              {
                                "long_name": "38108",
                                "short_name": "38108",
                                "types": [
                                  "postal_code"
                                ]
                              }
                            ],
                            "formatted_address": "Av. el Cardonal, 52, b, 38108 La Laguna, Santa Cruz de Tenerife, Spain",
                            "geometry": {
                              "location": {
                                "lat": 28.4501161,
                                "lng": -16.3004407
                              },
                              "location_type": "ROOFTOP"
                            },
                            "types": [
                              "street_address",
                              "subpremise"
                            ]
                          },
                          "document_location": {
                            "latitude": 28.4501161,
                            "longitude": -16.3004407
                          },
                          "label": "Spain Identity Card Address",
                          "is_verified": true,
                          "category": "Residential"
                        },
                        "warnings": [],
                        "barcodes": []
                      },
                      "vendor_data": "user-123",
                      "metadata": {
                        "flow": "onboarding"
                      },
                      "created_at": "2026-06-12T02:21:56.013573+00:00"
                    }
                  },
                  "Declined - expired document": {
                    "summary": "Téléversement du recto seul d'une carte d'identité expirée",
                    "value": {
                      "request_id": "f61681b8-9422-4378-ac3e-04c6a247fb45",
                      "id_verification": {
                        "status": "Declined",
                        "document_type": "Identity Card",
                        "document_subtype": "ID_CARD_GENERIC",
                        "document_number": "BNK123072",
                        "personal_number": "21771255F",
                        "portrait_image": "https://<media-host>/ocr/f61681b8-9422-4378-ac3e-04c6a247fb45-portrait_image-1d9a.jpg?signature=...",
                        "front_image": "https://<media-host>/ocr/f61681b8-9422-4378-ac3e-04c6a247fb45-front_image-5c2b.jpg?signature=...",
                        "back_image": null,
                        "front_image_camera_front": null,
                        "back_image_camera_front": null,
                        "front_image_camera_front_face_match_score": null,
                        "back_image_camera_front_face_match_score": null,
                        "front_image_quality_score": {
                          "focus_score": 100.0,
                          "brightness_score": 95.7,
                          "brightness_issue": "ok",
                          "is_document_fully_visible": true,
                          "resolution_score": 22.2,
                          "overall_score": 79.3
                        },
                        "back_image_quality_score": null,
                        "date_of_birth": "1997-01-30",
                        "age": 29,
                        "expiration_date": "2025-11-26",
                        "date_of_issue": null,
                        "issuing_state": "ESP",
                        "issuing_state_name": "Spain",
                        "first_name": "Lucia",
                        "last_name": "Marin Castro",
                        "full_name": "Lucia Marin Castro",
                        "gender": "F",
                        "address": null,
                        "formatted_address": null,
                        "place_of_birth": null,
                        "marital_status": "UNKNOWN",
                        "nationality": "ESP",
                        "extra_fields": {
                          "first_surname": "Marin",
                          "second_surname": "Castro"
                        },
                        "mrz": {},
                        "parsed_address": null,
                        "warnings": [
                          {
                            "risk": "DOCUMENT_EXPIRED",
                            "feature": "ID_VERIFICATION",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Document expired",
                            "long_description": "The document's expiration date has passed, rendering it no longer valid for use."
                          }
                        ],
                        "barcodes": []
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T02:25:48.117204+00:00"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "id_verification": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "Declined",
                            "In Review"
                          ],
                          "description": "`Approved` lorsqu'aucun avertissement n'aboutit à un refus et que la vérification de détection du vivant sur le document demandée a produit un résultat exploitable ; `In Review` lorsque cette vérification demandée n'a produit aucun résultat exploitable (`DOCUMENT_LIVENESS_NOT_COMPUTED`) ; `Declined` lorsqu'un avertissement aboutit à un refus — la liste `warnings` en explique la raison."
                        },
                        "document_type": {
                          "type": "string",
                          "nullable": true,
                          "description": "Nom d'affichage du type de document détecté : `Identity Card`, `Passport`, `Driver's License`, `Residence Permit`, `Health Insurance Card` ou `Tax Card`. `null` lorsque le document n'a pas pu être classé.",
                          "example": "Identity Card"
                        },
                        "document_subtype": {
                          "type": "string",
                          "nullable": true,
                          "description": "Sous-type plus détaillé lorsqu'il est disponible (par ex. `ID_CARD_GENERIC`, `EPASSPORT`).",
                          "example": "ID_CARD_GENERIC"
                        },
                        "document_number": {
                          "type": "string",
                          "nullable": true,
                          "example": "CBX164224"
                        },
                        "personal_number": {
                          "type": "string",
                          "nullable": true,
                          "description": "Numéro personnel/national secondaire imprimé sur certains documents.",
                          "example": "20446581H"
                        },
                        "portrait_image": {
                          "type": "string",
                          "nullable": true,
                          "description": "Photo de portrait recadrée du document. Une URL de média temporaire (`https://<media-host>/ocr/...`) lorsque `save_api_request=true` (par défaut) ; une chaîne JPEG encodée en base64 en ligne lorsque `save_api_request=false`. `null` lorsqu'aucun portrait n'a été détecté."
                        },
                        "front_image": {
                          "type": "string",
                          "nullable": true,
                          "description": "Recadrage aligné du recto du document. URL du média lorsqu'il est enregistré, JPEG intégré encodé en base64 sinon."
                        },
                        "back_image": {
                          "type": "string",
                          "nullable": true,
                          "description": "Recadrage aligné du verso du document. `null` si aucune `back_image` n'a été téléversée."
                        },
                        "front_image_camera_front": {
                          "type": "string",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint (renseigné uniquement dans les sessions de vérification par capture caméra)."
                        },
                        "back_image_camera_front": {
                          "type": "string",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint."
                        },
                        "front_image_camera_front_face_match_score": {
                          "type": "number",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint."
                        },
                        "back_image_camera_front_face_match_score": {
                          "type": "number",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint."
                        },
                        "front_image_quality_score": {
                          "type": "object",
                          "nullable": true,
                          "description": "Diagnostics de qualité de capture pour l'image téléversée (`null` lorsque le côté n'a pas été fourni ou que la notation a échoué). Tous les scores sont compris entre 0 et 100.",
                          "properties": {
                            "focus_score": {
                              "type": "number",
                              "format": "float",
                              "description": "Netteté du recadrage du document (une valeur plus élevée indique une plus grande netteté)."
                            },
                            "brightness_score": {
                              "type": "number",
                              "format": "float",
                              "description": "Qualité de l'exposition (plus elle est élevée, mieux c'est)."
                            },
                            "brightness_issue": {
                              "type": "string",
                              "nullable": true,
                              "description": "`ok` lorsque l'exposition est correcte, sinon le problème détecté (par ex. trop sombre / trop lumineux)."
                            },
                            "is_document_fully_visible": {
                              "type": "boolean",
                              "nullable": true,
                              "description": "Indique si les quatre coins du document se trouvent à l'intérieur du cadre."
                            },
                            "resolution_score": {
                              "type": "number",
                              "format": "float",
                              "description": "Résolution effective de la zone du document."
                            },
                            "overall_score": {
                              "type": "number",
                              "format": "float",
                              "description": "Score de qualité agrégé."
                            }
                          }
                        },
                        "back_image_quality_score": {
                          "type": "object",
                          "nullable": true,
                          "description": "Diagnostics de qualité de capture pour l'image téléversée (`null` lorsque le côté n'a pas été fourni ou que la notation a échoué). Tous les scores sont compris entre 0 et 100.",
                          "properties": {
                            "focus_score": {
                              "type": "number",
                              "format": "float",
                              "description": "Netteté du recadrage du document (une valeur plus élevée indique une plus grande netteté)."
                            },
                            "brightness_score": {
                              "type": "number",
                              "format": "float",
                              "description": "Qualité de l'exposition (plus elle est élevée, mieux c'est)."
                            },
                            "brightness_issue": {
                              "type": "string",
                              "nullable": true,
                              "description": "`ok` lorsque l'exposition est correcte, sinon le problème détecté (par ex. trop sombre / trop lumineux)."
                            },
                            "is_document_fully_visible": {
                              "type": "boolean",
                              "nullable": true,
                              "description": "Indique si les quatre coins du document se trouvent à l'intérieur du cadre."
                            },
                            "resolution_score": {
                              "type": "number",
                              "format": "float",
                              "description": "Résolution effective de la zone du document."
                            },
                            "overall_score": {
                              "type": "number",
                              "format": "float",
                              "description": "Score de qualité agrégé."
                            }
                          }
                        },
                        "date_of_birth": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "example": "1980-01-13"
                        },
                        "age": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Âge du titulaire en années, calculé à partir de `date_of_birth`.",
                          "example": 46
                        },
                        "expiration_date": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "example": "2032-03-31"
                        },
                        "date_of_issue": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "example": "2022-03-31"
                        },
                        "issuing_state": {
                          "type": "string",
                          "nullable": true,
                          "description": "Pays de délivrance (ISO 3166-1 alpha-3).",
                          "example": "ESP"
                        },
                        "issuing_state_name": {
                          "type": "string",
                          "nullable": true,
                          "example": "Spain"
                        },
                        "first_name": {
                          "type": "string",
                          "nullable": true,
                          "example": "Julio Francisco"
                        },
                        "last_name": {
                          "type": "string",
                          "nullable": true,
                          "example": "Fores Sena"
                        },
                        "full_name": {
                          "type": "string",
                          "nullable": true,
                          "example": "Julio Francisco Fores Sena"
                        },
                        "gender": {
                          "type": "string",
                          "nullable": true,
                          "description": "`M`, `F` ou `null` lorsqu'il n'est pas imprimé/détecté.",
                          "example": "M"
                        },
                        "address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Adresse exactement telle qu'elle est imprimée sur le document."
                        },
                        "formatted_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Version géocodée et normalisée de `address`."
                        },
                        "place_of_birth": {
                          "type": "string",
                          "nullable": true,
                          "example": "Valencia, Valencia"
                        },
                        "marital_status": {
                          "type": "string",
                          "nullable": true,
                          "description": "`UNKNOWN` sauf si le document indique la situation matrimoniale.",
                          "example": "UNKNOWN"
                        },
                        "nationality": {
                          "type": "string",
                          "nullable": true,
                          "description": "Nationalité du titulaire (ISO 3166-1 alpha-3).",
                          "example": "ESP"
                        },
                        "extra_fields": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true,
                          "description": "Champs supplémentaires spécifiques au document ne disposant pas de colonne dédiée (par ex. `first_surname`/`second_surname` sur les pièces d'identité espagnoles, catégories de permis sur les permis de conduire)."
                        },
                        "mrz": {
                          "type": "object",
                          "description": "Zone de lecture optique analysée. Un **objet vide** (`{}`) si le document n'a pas de MRZ ou si elle n'a pas pu être lue — vérifiez également la liste `warnings` dans ce cas. Les dates à l'intérieur de la MRZ utilisent le format brut `YYMMDD`.",
                          "properties": {
                            "surname": {
                              "type": "string",
                              "example": "FORES SENA"
                            },
                            "name": {
                              "type": "string",
                              "example": "JULIO FRANCISCO"
                            },
                            "country": {
                              "type": "string",
                              "description": "Pays de délivrance (ISO 3166-1 alpha-3).",
                              "example": "ESP"
                            },
                            "nationality": {
                              "type": "string",
                              "description": "Nationalité du titulaire (ISO 3166-1 alpha-3).",
                              "example": "ESP"
                            },
                            "birth_date": {
                              "type": "string",
                              "description": "Date de naissance MRZ brute (`YYMMDD`).",
                              "example": "800113"
                            },
                            "expiry_date": {
                              "type": "string",
                              "description": "Date d'expiration MRZ brute (`YYMMDD`).",
                              "example": "320331"
                            },
                            "sex": {
                              "type": "string",
                              "example": "M"
                            },
                            "document_type": {
                              "type": "string",
                              "description": "Code de type de document MRZ (par ex. `ID`, `P`).",
                              "example": "ID"
                            },
                            "document_number": {
                              "type": "string",
                              "example": "CBX164224"
                            },
                            "optional_data": {
                              "type": "string",
                              "nullable": true,
                              "example": "20446581H"
                            },
                            "optional_data_2": {
                              "type": "string",
                              "nullable": true,
                              "example": ""
                            },
                            "birth_date_hash": {
                              "type": "string",
                              "description": "Chiffre de contrôle MRZ pour la date de naissance.",
                              "example": "9"
                            },
                            "expiry_date_hash": {
                              "type": "string",
                              "description": "Chiffre de contrôle MRZ pour la date d'expiration.",
                              "example": "8"
                            },
                            "document_number_hash": {
                              "type": "string",
                              "description": "Chiffre de contrôle MRZ pour le numéro de document.",
                              "example": "3"
                            },
                            "final_hash": {
                              "type": "string",
                              "description": "Chiffre de contrôle composite de la MRZ.",
                              "example": "3"
                            },
                            "personal_number": {
                              "type": "string",
                              "nullable": true,
                              "example": "20446581H"
                            },
                            "warnings": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Avertissements non fatals lors de l'analyse de la MRZ."
                            },
                            "errors": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Erreurs de chiffre de contrôle / d'analyse MRZ. Les erreurs non vides apparaissent sous forme d'avertissement `MRZ_VALIDATION_FAILED`."
                            },
                            "mrz_type": {
                              "type": "string",
                              "description": "Format MRZ : `TD1` (cartes d'identité, 3 lignes), `TD2` ou `TD3` (passeports, 2 lignes).",
                              "example": "TD1"
                            },
                            "mrz_string": {
                              "type": "string",
                              "description": "Texte MRZ brut tel que lu, lignes séparées par `\\n`."
                            },
                            "mrz_key": {
                              "type": "string",
                              "description": "Clé composite (numéro de document + chiffres de contrôle) utilisée pour les vérifications croisées."
                            }
                          }
                        },
                        "parsed_address": {
                          "type": "object",
                          "nullable": true,
                          "description": "Détail structuré et géocodé de `address`. `null` lorsque le document ne comporte aucune adresse ou si elle n'a pas pu être analysée.",
                          "properties": {
                            "street_1": {
                              "type": "string",
                              "nullable": true,
                              "example": "Avenida el Cardonal 52"
                            },
                            "street_2": {
                              "type": "string",
                              "nullable": true,
                              "example": "b"
                            },
                            "city": {
                              "type": "string",
                              "nullable": true,
                              "example": "La Laguna"
                            },
                            "region": {
                              "type": "string",
                              "nullable": true,
                              "example": "Canarias"
                            },
                            "country": {
                              "type": "string",
                              "nullable": true,
                              "description": "Code pays ISO 3166-1 alpha-2.",
                              "example": "ES"
                            },
                            "postal_code": {
                              "type": "string",
                              "nullable": true,
                              "example": "38108"
                            },
                            "address_type": {
                              "type": "string",
                              "nullable": true,
                              "example": "Avenida"
                            },
                            "formatted_address": {
                              "type": "string",
                              "nullable": true,
                              "description": "Chaîne d'adresse géocodée canonique.",
                              "example": "Av. el Cardonal, 52, b, 38108 La Laguna, Santa Cruz de Tenerife, Spain"
                            },
                            "raw_results": {
                              "type": "object",
                              "additionalProperties": true,
                              "description": "Payload brut de géocodage (`address_components`, `geometry.location`, `place_id`, …) pour les consommateurs avancés."
                            },
                            "document_location": {
                              "type": "object",
                              "nullable": true,
                              "properties": {
                                "latitude": {
                                  "type": "number"
                                },
                                "longitude": {
                                  "type": "number"
                                }
                              },
                              "description": "Coordonnées géocodées de l'adresse figurant sur le document."
                            },
                            "label": {
                              "type": "string",
                              "nullable": true,
                              "description": "Quel champ du document a permis de lire l'adresse.",
                              "example": "Spain Identity Card Address"
                            },
                            "is_verified": {
                              "type": "boolean",
                              "description": "Indique si le géocodage a confirmé l'existence de l'adresse."
                            },
                            "category": {
                              "type": "string",
                              "nullable": true,
                              "description": "Catégorie d'adresse (par exemple `Residential`, `Commercial`).",
                              "example": "Residential"
                            }
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "description": "Vide en cas d'approbation sans réserve. Chaque entrée explique un risque détecté ; les entrées avec `log_type: \"error\"` définissent `status` sur `Declined`, et `DOCUMENT_LIVENESS_NOT_COMPUTED` (`log_type: \"warning\"`) le définit sur `In Review`.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "risk": {
                                "type": "string",
                                "description": "Code de risque lisible par machine. Risques entraînant toujours un refus : `DOCUMENT_EXPIRED`, `MINIMUM_AGE_NOT_MET`, `PORTRAIT_IMAGE_NOT_DETECTED`, `SCREEN_CAPTURE_DETECTED`, `PRINTED_COPY_DETECTED`, `PORTRAIT_MANIPULATION_DETECTED`, `PUBLIC_DOCUMENT_IMAGE_DETECTED`, `INVALID_DATE`, `COULD_NOT_RECOGNIZE_DOCUMENT` (400 uniquement, jamais un avertissement), `DOCUMENT_NUMBER_NOT_DETECTED`, `COULD_NOT_DETECT_DOCUMENT_TYPE`, `NAME_NOT_DETECTED`, `DATE_OF_BIRTH_NOT_DETECTED`. Régis par les options de requête : `MRZ_NOT_DETECTED` / `MRZ_VALIDATION_FAILED` (`invalid_mrz_action`), `DATA_INCONSISTENT` / `MRZ_AND_DATA_EXTRACTED_FROM_OCR_NOT_SAME` / `DOCUMENT_NAME_DIFFERENT_FROM_OTHER_APPROVED_DOCUMENTS` (`inconsistent_data_action`), `EXPIRATION_DATE_NOT_DETECTED` (`expiration_date_not_detected_action`). Les autres risques (par ex. `POSSIBLE_DUPLICATED_USER`) sont informatifs. `DOCUMENT_LIVENESS_NOT_COMPUTED` est déclenché lorsque `perform_document_liveness=true` mais que le contrôle de contrefaçon n'a renvoyé aucun score exploitable ; cela définit `status` sur `In Review`. `COULD_NOT_DETECT_DOCUMENT_TYPE` est également renvoyé lorsque le recto du document ne correspond pas avec un niveau de confiance élevé au modèle d'un document officiel connu, par exemple un document modifié ou généré par ordinateur, ou un modèle qui n'est pas encore pris en charge.",
                                "example": "DOCUMENT_EXPIRED"
                              },
                              "feature": {
                                "type": "string",
                                "enum": [
                                  "ID_VERIFICATION"
                                ],
                                "description": "Fonctionnalité ayant émis l'avertissement. Toujours `ID_VERIFICATION` sur cet endpoint."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "additionalProperties": true,
                                "description": "Contexte supplémentaire pour certains risques (par ex. `POSSIBLE_DUPLICATED_USER` inclut `duplicated_session_id`) ; `null` pour la plupart."
                              },
                              "log_type": {
                                "type": "string",
                                "enum": [
                                  "error",
                                  "warning",
                                  "information"
                                ],
                                "description": "Gravité. Les avertissements `error` font passer `status` à `Declined` ; `warning` (uniquement `DOCUMENT_LIVENESS_NOT_COMPUTED`, lorsque le contrôle de falsification demandé n'a produit aucun score utilisable) fait passer `status` à `In Review` ; les entrées `information` sont indicatives et ne modifient jamais le statut."
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Résumé du risque en une ligne, lisible par l'utilisateur."
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication lisible par l'humain du risque."
                              }
                            }
                          }
                        },
                        "barcodes": {
                          "type": "array",
                          "description": "Codes-barres décodés à partir du document (PDF417, QR, …). Vide lorsque le document n'en comporte aucun ou qu'aucun n'a pu être lu.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "description": "Type de code-barres (par ex. `PDF417`, `QR_CODE`, `UNKNOWN`)."
                              },
                              "position": {
                                "type": "object",
                                "nullable": true,
                                "additionalProperties": true,
                                "description": "Emplacement du code-barres dans l'image, lorsqu'il est disponible."
                              },
                              "data": {
                                "type": "string",
                                "description": "Payload décodé."
                              },
                              "data_raw": {
                                "type": "string",
                                "description": "Payload brut (non décodé), lorsqu'il est différent."
                              },
                              "side": {
                                "type": "string",
                                "nullable": true,
                                "description": "`front` ou `back`."
                              }
                            }
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Écho des `vendor_data` que vous avez envoyées, ou `null`."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Écho de l'objet `metadata` que vous avez envoyé, ou `null`."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Horodatage ISO 8601 (UTC) du moment où la réponse a été générée."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation ou de traitement. Les problèmes au niveau des champs renvoient l'enveloppe standard de DRF (un tableau de messages par champ concerné). Les problèmes de PDF chiffré renvoient `{\"detail\": ...}`. Une image de document dans laquelle aucun document ne peut être reconnu renvoie `{\"error\": \"COULD_NOT_RECOGNIZE_DOCUMENT\"}`. Les téléversements de PDF peuvent également échouer avec « Le fichier PDF soumis est corrompu ou non valide. » ou une erreur d'absence de pages.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing front image": {
                    "summary": "`front_image` n'est pas inclus dans les données du formulaire",
                    "value": {
                      "front_image": [
                        "No file was submitted."
                      ]
                    }
                  },
                  "Unsupported file extension": {
                    "summary": "Extension de fichier autre que tiff/jpg/jpeg/png/webp/pdf",
                    "value": {
                      "front_image": [
                        "File extension “txt” is not allowed. Allowed extensions are: tiff, jpg, jpeg, png, webp, pdf."
                      ]
                    }
                  },
                  "File too large": {
                    "summary": "Le téléversement dépasse la limite de 10 MB",
                    "value": {
                      "front_image": [
                        "File size should not exceed 10 MB"
                      ]
                    }
                  },
                  "Invalid option value": {
                    "summary": "Les options acceptent uniquement DECLINE ou NO_ACTION",
                    "value": {
                      "invalid_mrz_action": [
                        "\"REVIEW\" is not a valid choice."
                      ]
                    }
                  },
                  "Encrypted PDF": {
                    "summary": "PDF téléversé sans le mot de passe requis",
                    "value": {
                      "detail": "The PDF is encrypted. Please upload a decrypted PDF or a photo instead."
                    }
                  },
                  "Wrong PDF password": {
                    "summary": "`front_image_password` / `back_image_password` ne déchiffrent pas le PDF",
                    "value": {
                      "detail": "The PDF password is incorrect. Please provide the correct password."
                    }
                  },
                  "Document not recognized": {
                    "summary": "Aucun document d'identité n'a pu être détecté dans l'image",
                    "value": {
                      "error": "COULD_NOT_RECOGNIZE_DOCUMENT"
                    }
                  },
                  "PDF conversion failure": {
                    "summary": "Le PDF téléversé n'a pas pu être converti en image",
                    "value": {
                      "error": "Failed to convert front image PDF."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout traitement d'image.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/DocumentProcessingBusy"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/id-verification/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'front_image=@./id_front.jpg' \\\n  -F 'back_image=@./id_back.jpg' \\\n  -F 'perform_document_liveness=true' \\\n  -F 'save_api_request=true' \\\n  -F 'vendor_data=user-123'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_verification.verify(\n    front_image=open(\"front_image.jpg\", \"rb\"),\n    back_image=open(\"back_image.jpg\", \"rb\"),\n    perform_document_liveness=True,\n    save_api_request=True,\n    vendor_data=\"user-123\",\n    metadata={\"flow\": \"onboarding\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idVerification.verify({\n  front_image: await fileFromPath(\"front_image.jpg\"),\n  back_image: await fileFromPath(\"back_image.jpg\"),\n  perform_document_liveness: true,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"onboarding\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDVerification.Verify(ctx, didit.IDVerificationVerifyParams{\n\tFrontImage:              didit.FileFromPath(\"front_image.jpg\"),\n\tBackImage:               didit.Some(didit.FileFromPath(\"back_image.jpg\")),\n\tPerformDocumentLiveness: didit.Bool(true),\n\tSaveAPIRequest:          didit.Bool(true),\n\tVendorData:              didit.String(\"user-123\"),\n\tMetadata:                didit.Some(map[string]any{\"flow\": \"onboarding\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.IdVerificationVerifyParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idVerification().verify(IdVerificationVerifyParams.builder()\n        .frontImage(Path.of(\"front_image.jpg\"))\n        .backImage(Path.of(\"back_image.jpg\"))\n        .performDocumentLiveness(true)\n        .saveApiRequest(true)\n        .vendorData(\"user-123\")\n        .metadata(Map.of(\"flow\", \"onboarding\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idVerification->verify([\n    'front_image' => File::fromPath('front_image.jpg'),\n    'back_image' => File::fromPath('back_image.jpg'),\n    'perform_document_liveness' => true,\n    'save_api_request' => true,\n    'vendor_data' => 'user-123',\n    'metadata' => ['flow' => 'onboarding'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_verification.verify(\n  front_image: Pathname(\"front_image.jpg\"),\n  back_image: Pathname(\"back_image.jpg\"),\n  perform_document_liveness: true,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"onboarding\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdVerification.VerifyAsync(new IdVerificationVerifyParams\n{\n    FrontImage = FileUpload.FromPath(\"front_image.jpg\"),\n    BackImage = FileUpload.FromPath(\"back_image.jpg\"),\n    PerformDocumentLiveness = true,\n    SaveApiRequest = true,\n    VendorData = \"user-123\",\n    Metadata = new Dictionary<string, object> { [\"flow\"] = \"onboarding\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/face-match/": {
      "post": {
        "summary": "Correspondance faciale",
        "description": "Compare deux images faciales (1:1) et renvoie un `score` de similarité (0–100) ainsi qu'un `status` `Approved`/`Declined`.\n\n**Fonctionnement.** Les deux images sont décodées et analysées par un modèle biométrique (définissez `rotate_image=true` si les captures peuvent être de biais ou inversées), puis un score de similarité entre les deux visages est calculé. Un score **strictement supérieur** à `face_match_score_decline_threshold` (par défaut `30`) renvoie `status: \"Approved\"` ; un score inférieur ou égal renvoie `Declined` avec un avertissement `LOW_FACE_MATCH_SIMILARITY`. Si aucune paire de visages ne peut être évaluée, l'appel renvoie tout de même `200` avec `status: \"Declined\"` et un avertissement `NO_REFERENCE_IMAGE` — `score` est `null` sur le chemin d'enregistrement par défaut, ou `0` avec `save_api_request=false`. Soumettez un visage net et de face par image pour de meilleurs résultats.\n\n**Facturation.** Chaque réponse `200` consomme un crédit d'API Face Match (débité de votre crédit de forfait ou de votre solde de recharge). Lorsque le solde de l'organisation ne peut pas couvrir l'appel, l'endpoint renvoie `403` avec l'erreur de crédits insuffisants avant tout traitement d'image.\n\n**Persistance de la session (`save_api_request`, par défaut `true`).** Lorsqu'il vaut `true`, l'appel est conservé sous forme de session de type API : il apparaît dans la Business Console, le `request_id` renvoyé est un véritable identifiant de session que vous pouvez passer à `GET /v3/session/{sessionId}/decision/`, les deux images sont stockées en tant qu'images source/cible de correspondance faciale de la session, et un webhook `status.updated` est émis vers vos destinations de webhook configurées. Lorsqu'il vaut `false`, rien n'est stocké et `request_id` est un UUID de corrélation à usage unique qui ne peut pas être consulté ultérieurement.\n\n**Index de recherche faciale.** Cet endpoint n'enrôle jamais de visages dans votre index de recherche faciale et n'exécute jamais de filtrage de liste de blocage ou de doublons — utilisez `POST /v3/passive-liveness/` ou `POST /v3/face-search/` pour cela.\n\n**Sandbox.** Les clés API de sandbox ignorent tout traitement et toute facturation : après validation de la requête (une entrée malformée renvoie toujours `400`), l'endpoint renvoie un payload fictif statique `Approved`, aucune session n'est conservée et aucun crédit n'est consommé.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou non valides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) — cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes/min par clé API sur l'ensemble des endpoints POST/PATCH/DELETE ; le dépasser renvoie `429`.",
        "operationId": "post_v3face-match",
        "x-didit-sdk": {
          "resource": "face_match",
          "method": "compare",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "user_image",
                  "ref_image"
                ],
                "properties": {
                  "user_image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Image d'un visage vivant ou d'un visage candidat à vérifier (p. ex. un selfie). Soumettez une seule photo de face avec le visage du sujet clairement visible et bien éclairé. Extensions autorisées : `tiff`, `jpg`, `jpeg`, `png`, `webp`. Taille maximale de téléversement : **5 MB** (les fichiers plus volumineux sont rejetés avec `400`). Les images sont automatiquement compressées à environ 0,5 MB avant le traitement, de sorte que des résolutions très élevées n'améliorent pas la précision."
                  },
                  "ref_image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Image faciale de référence à comparer (par ex. un portrait de pièce d'identité ou une photo enregistrée au préalable). Même format et mêmes limites de taille que pour `user_image`."
                  },
                  "face_match_score_decline_threshold": {
                    "type": "number",
                    "format": "float",
                    "default": 30,
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Seuil de similarité (0–100) qui détermine le `status` de la réponse. Un score calculé **inférieur ou égal** à cette valeur définit `status` sur `Declined` et ajoute un avertissement `LOW_FACE_MATCH_SIMILARITY` ; un score strictement supérieur renvoie `Approved`. La valeur par défaut de `30` est permissive — augmentez-la (par ex. `50`–`60`) pour une vérification plus stricte. Les valeurs en dehors de 0–100 renvoient `400`.",
                    "example": 50
                  },
                  "rotate_image": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lorsque la valeur est `true`, le service teste les images fournies par incréments de 90 degrés (0, 90, 180, 270) et utilise l'orientation qui produit la meilleure détection faciale — utile pour les captures mobiles sans orientation EXIF. Ajoute de la latence, ne l'activez donc que si vous ne pouvez pas garantir des images dans le bon sens.",
                    "example": false
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Lorsque la valeur est `true` (par défaut), conserve l'appel sous la forme d'une session de type API — visible dans la Business Console, récupérable via `GET /v3/session/{sessionId}/decision/` à l'aide du `request_id` renvoyé, et notifiée via un webhook `status.updated`. Lorsque la valeur est `false`, rien n'est stocké et `request_id` est un UUID éphémère servant uniquement à la corrélation des réponses.",
                    "example": true
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Chaîne opaque optionnelle (votre identifiant d'utilisateur interne, e-mail, UUID…) stockée sur la session persistée et renvoyée dans la réponse. Utilisez-la pour corréler les appels d'API avec vos propres enregistrements et pour filtrer les sessions ultérieurement.",
                    "example": "user-123"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Objet JSON optionnel stocké avec la session (lorsque `save_api_request=true`) et renvoyé dans la réponse. Dans les requêtes multipart, envoyez-le sous forme de champ textuel encodé en JSON (par ex. `metadata={\"flow\":\"login\"}`) — il est analysé sous forme d'objet.",
                    "example": {
                      "flow": "login",
                      "device_id": "abc123"
                    }
                  }
                }
              },
              "example": {
                "user_image": "(binary JPEG/PNG of the live selfie)",
                "ref_image": "(binary JPEG/PNG of the reference photo)",
                "face_match_score_decline_threshold": 50,
                "rotate_image": false,
                "save_api_request": true,
                "vendor_data": "user-123",
                "metadata": {
                  "flow": "login"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Correspondance faciale calculée. `face_match.score` est un nombre flottant compris entre 0 et 100 (deux décimales) ; `status` est `Approved` lorsque le score est strictement supérieur à `face_match_score_decline_threshold`, sinon `Declined` avec un avertissement explicatif. Une faible similarité ou une paire non évaluable renvoie toujours `200` — inspectez `face_match.status` et `face_match.warnings`, pas seulement le code HTTP. Lorsque `save_api_request=true`, `request_id` est l'identifiant de la session conservée.",
            "content": {
              "application/json": {
                "examples": {
                  "Approved": {
                    "summary": "Même personne — score supérieur au seuil",
                    "value": {
                      "request_id": "f9f5a777-8002-44c6-baaf-128bcfd6e226",
                      "face_match": {
                        "status": "Approved",
                        "score": 99.41,
                        "user_image": {
                          "entities": [
                            {
                              "bbox": [
                                661,
                                728,
                                1688,
                                2188
                              ],
                              "confidence": 0.732973,
                              "age": 26.91,
                              "gender": "male",
                              "race": null
                            }
                          ],
                          "best_angle": 0
                        },
                        "ref_image": {
                          "entities": [
                            {
                              "bbox": [
                                653,
                                745,
                                1691,
                                2185
                              ],
                              "confidence": 0.722082,
                              "age": 27.0,
                              "gender": "male",
                              "race": null
                            }
                          ],
                          "best_angle": 0
                        },
                        "warnings": []
                      },
                      "vendor_data": "user-123",
                      "metadata": {
                        "flow": "login"
                      },
                      "created_at": "2026-06-12T01:04:42.763237+00:00"
                    }
                  },
                  "Declined - low similarity": {
                    "summary": "Score inférieur ou égal au seuil de refus",
                    "value": {
                      "request_id": "7cdda24e-311a-46d3-a3bb-e5d9b564ce73",
                      "face_match": {
                        "status": "Declined",
                        "score": 24.87,
                        "user_image": {
                          "entities": [
                            {
                              "bbox": [
                                661,
                                728,
                                1688,
                                2188
                              ],
                              "confidence": 0.732973,
                              "age": 26.91,
                              "gender": "male",
                              "race": null
                            }
                          ],
                          "best_angle": 0
                        },
                        "ref_image": {
                          "entities": [
                            {
                              "bbox": [
                                156,
                                234,
                                679,
                                898
                              ],
                              "confidence": 0.717775,
                              "age": 41.2,
                              "gender": "male",
                              "race": null
                            }
                          ],
                          "best_angle": 0
                        },
                        "warnings": [
                          {
                            "risk": "LOW_FACE_MATCH_SIMILARITY",
                            "feature": "FACEMATCH",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Low face match similarity",
                            "long_description": "The facial features of the provided image don't closely match the reference image, suggesting a potential identity mismatch."
                          }
                        ]
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T01:08:19.859116+00:00"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "face_match": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "Declined"
                          ],
                          "description": "`Approved` lorsque le score de similarité est strictement supérieur à `face_match_score_decline_threshold` et qu'un score a pu être calculé ; `Declined` dans le cas contraire (un avertissement en explique la raison)."
                        },
                        "score": {
                          "type": "number",
                          "format": "float",
                          "nullable": true,
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Score de similarité de 0 à 100 — niveau de confiance du modèle quant au fait que les deux images représentent la même personne. Arrondi à deux décimales uniquement lorsque `save_api_request` est défini sur true ; avec `save_api_request=false`, le nombre à virgule flottante brut est renvoyé. `null` lorsqu'aucune paire de visages n'a pu être notée (avec `save_api_request=true` par défaut) ; avec `save_api_request=false`, cette même situation peut apparaître sous la forme `score: 0`. Dans les deux cas, un avertissement `NO_REFERENCE_IMAGE` est présent et `status` est `Declined`.",
                          "example": 99.41
                        },
                        "user_image": {
                          "type": "object",
                          "description": "Résultats de la détection faciale pour les images analysées.",
                          "properties": {
                            "entities": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "bbox": {
                                    "type": "array",
                                    "items": {
                                      "type": "integer"
                                    },
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "description": "Boîte englobante du visage détecté sous forme de coordonnées en pixels `[x_min, y_min, x_max, y_max]` dans l'image traitée.",
                                    "example": [
                                      661,
                                      728,
                                      1688,
                                      2188
                                    ]
                                  },
                                  "confidence": {
                                    "type": "number",
                                    "format": "float",
                                    "minimum": 0,
                                    "maximum": 1,
                                    "description": "Indice de confiance de la détection faciale (0–1).",
                                    "example": 0.732973
                                  },
                                  "age": {
                                    "type": "number",
                                    "format": "float",
                                    "description": "Âge estimé par le modèle pour le visage détecté, en années. À titre informatif uniquement — n'affecte pas la décision de correspondance faciale.",
                                    "example": 26.91
                                  },
                                  "gender": {
                                    "type": "string",
                                    "description": "Genre prédit par le modèle pour le visage détecté (`male` ou `female`). À titre informatif uniquement.",
                                    "example": "male"
                                  },
                                  "race": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "Champ réservé — toujours `null` dans les réponses de cet endpoint.",
                                    "example": null
                                  }
                                }
                              },
                              "description": "Une entrée par visage détecté."
                            },
                            "best_angle": {
                              "type": "integer",
                              "description": "Rotation (en degrés : 0, 90, 180 ou 270) ayant produit la meilleure détection de visage. Non nulle uniquement lorsque `rotate_image=true` a corrigé l'orientation.",
                              "example": 0
                            }
                          }
                        },
                        "ref_image": {
                          "type": "object",
                          "description": "Résultats de la détection faciale pour l'image de référence, même format que `user_image`.",
                          "properties": {
                            "entities": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "bbox": {
                                    "type": "array",
                                    "items": {
                                      "type": "integer"
                                    },
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "description": "Boîte englobante du visage détecté sous forme de coordonnées en pixels `[x_min, y_min, x_max, y_max]` dans l'image traitée.",
                                    "example": [
                                      661,
                                      728,
                                      1688,
                                      2188
                                    ]
                                  },
                                  "confidence": {
                                    "type": "number",
                                    "format": "float",
                                    "minimum": 0,
                                    "maximum": 1,
                                    "description": "Indice de confiance de la détection faciale (0–1).",
                                    "example": 0.732973
                                  },
                                  "age": {
                                    "type": "number",
                                    "format": "float",
                                    "description": "Âge estimé par le modèle pour le visage détecté, en années. À titre informatif uniquement — n'affecte pas la décision de correspondance faciale.",
                                    "example": 26.91
                                  },
                                  "gender": {
                                    "type": "string",
                                    "description": "Genre prédit par le modèle pour le visage détecté (`male` ou `female`). À titre informatif uniquement.",
                                    "example": "male"
                                  },
                                  "race": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "Champ réservé — toujours `null` dans les réponses de cet endpoint.",
                                    "example": null
                                  }
                                }
                              },
                              "description": "Une entrée par visage détecté."
                            },
                            "best_angle": {
                              "type": "integer",
                              "example": 0
                            }
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "description": "Vide en cas d'approbation sans réserve. `NO_REFERENCE_IMAGE` (`error`) — aucune paire de visages n'a pu être évaluée ; `LOW_FACE_MATCH_SIMILARITY` (`error`) — score inférieur ou égal au seuil de refus. N'importe lequel d'entre eux définit `status` sur `Declined`.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "risk": {
                                "type": "string",
                                "enum": [
                                  "NO_REFERENCE_IMAGE",
                                  "LOW_FACE_MATCH_SIMILARITY"
                                ],
                                "description": "Code de risque lisible par machine."
                              },
                              "feature": {
                                "type": "string",
                                "enum": [
                                  "FACEMATCH"
                                ],
                                "description": "Fonctionnalité ayant émis l'avertissement. Toujours `FACEMATCH` sur cet endpoint."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "additionalProperties": true,
                                "description": "Toujours `null` pour les avertissements de correspondance faciale."
                              },
                              "log_type": {
                                "type": "string",
                                "enum": [
                                  "error",
                                  "warning",
                                  "information"
                                ],
                                "description": "Gravité. Les avertissements `error` font passer `status` à `Declined` ; les entrées `warning` et `information` sont indicatives et ne refusent jamais d'elles-mêmes."
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Résumé du risque en une ligne, lisible par l'utilisateur."
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication lisible par l'humain du risque."
                              }
                            }
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Écho des `vendor_data` que vous avez envoyées, ou `null`."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Écho de l'objet `metadata` que vous avez envoyé, ou `null`."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Horodatage ISO 8601 (UTC) du moment où la réponse a été générée, ex. `2026-06-12T01:04:42.763237+00:00`."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Renvoyée lorsqu'une image requise est manquante, dépasse 5 Mo, possède une extension non prise en charge, ou lorsqu'une option est hors limites. Le corps est l'enveloppe standard d'erreur de champ de DRF : un tableau de messages par champ en cause.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing required image": {
                    "summary": "`ref_image` (ou `user_image`) non inclus dans les données de formulaire",
                    "value": {
                      "ref_image": [
                        "No file was submitted."
                      ]
                    }
                  },
                  "Unsupported file extension": {
                    "summary": "Extension de fichier autre que tiff/jpg/jpeg/png/webp",
                    "value": {
                      "user_image": [
                        "File extension “txt” is not allowed. Allowed extensions are: tiff, jpg, jpeg, png, webp."
                      ]
                    }
                  },
                  "File too large": {
                    "summary": "Le téléversement dépasse la limite de 5 MB",
                    "value": {
                      "user_image": [
                        "File size should not exceed 5 MB"
                      ]
                    }
                  },
                  "Threshold out of range": {
                    "summary": "`face_match_score_decline_threshold` hors de 0–100",
                    "value": {
                      "face_match_score_decline_threshold": [
                        "Ensure this value is less than or equal to 100."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout traitement d'image.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/face-match/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'user_image=@./selfie.jpg' \\\n  -F 'ref_image=@./id_portrait.jpg' \\\n  -F 'face_match_score_decline_threshold=50' \\\n  -F 'save_api_request=true' \\\n  -F 'vendor_data=user-123'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.face_match.compare(\n    user_image=open(\"user_image.jpg\", \"rb\"),\n    ref_image=open(\"ref_image.jpg\", \"rb\"),\n    face_match_score_decline_threshold=50.0,\n    rotate_image=False,\n    save_api_request=True,\n    vendor_data=\"user-123\",\n    metadata={\"flow\": \"login\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.faceMatch.compare({\n  user_image: await fileFromPath(\"user_image.jpg\"),\n  ref_image: await fileFromPath(\"ref_image.jpg\"),\n  face_match_score_decline_threshold: 50.0,\n  rotate_image: false,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"login\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.FaceMatch.Compare(ctx, didit.FaceMatchCompareParams{\n\tUserImage:                      didit.FileFromPath(\"user_image.jpg\"),\n\tRefImage:                       didit.FileFromPath(\"ref_image.jpg\"),\n\tFaceMatchScoreDeclineThreshold: didit.Float(50.0),\n\tRotateImage:                    didit.Bool(false),\n\tSaveAPIRequest:                 didit.Bool(true),\n\tVendorData:                     didit.String(\"user-123\"),\n\tMetadata:                       didit.Some(map[string]any{\"flow\": \"login\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.FaceMatchCompareParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.faceMatch().compare(FaceMatchCompareParams.builder()\n        .userImage(Path.of(\"user_image.jpg\"))\n        .refImage(Path.of(\"ref_image.jpg\"))\n        .faceMatchScoreDeclineThreshold(50.0)\n        .rotateImage(false)\n        .saveApiRequest(true)\n        .vendorData(\"user-123\")\n        .metadata(Map.of(\"flow\", \"login\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->faceMatch->compare([\n    'user_image' => File::fromPath('user_image.jpg'),\n    'ref_image' => File::fromPath('ref_image.jpg'),\n    'face_match_score_decline_threshold' => 50.0,\n    'rotate_image' => false,\n    'save_api_request' => true,\n    'vendor_data' => 'user-123',\n    'metadata' => ['flow' => 'login'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.face_match.compare(\n  user_image: Pathname(\"user_image.jpg\"),\n  ref_image: Pathname(\"ref_image.jpg\"),\n  face_match_score_decline_threshold: 50.0,\n  rotate_image: false,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"login\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.FaceMatch.CompareAsync(new FaceMatchCompareParams\n{\n    UserImage = FileUpload.FromPath(\"user_image.jpg\"),\n    RefImage = FileUpload.FromPath(\"ref_image.jpg\"),\n    FaceMatchScoreDeclineThreshold = 50.0,\n    RotateImage = false,\n    SaveApiRequest = true,\n    VendorData = \"user-123\",\n    Metadata = new Dictionary<string, object> { [\"flow\"] = \"login\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/age-estimation/": {
      "post": {
        "summary": "Estimation de l'âge (âge du visage + détection passive du vivant)",
        "description": "Estimez l'âge d'une personne à partir d'une seule photo de visage et effectuez une vérification passive du vivant dans le même appel — renvoie l'`age_estimation` prédit par le modèle (en années), un `score` de vivacité (0–100) et un `status` `Approved`/`Declined`. L'âge est **prédit par le modèle à partir du visage, non vérifié par rapport à un document** — utilisez-le pour les contrôles d'accès par âge et les vérifications à faible friction, et non comme preuve légale de l'âge.\n\n**Fonctionnement.** L'image est analysée pour détecter les visages (définissez `rotate_image=true` si les captures peuvent être inclinées ou inversées) ; chaque visage détecté reçoit un âge estimé, et le plus grand visage dans le cadre détermine `age_estimation`. En parallèle, un modèle passif de détection du vivant évalue si la photo montre une personne vivante (aucun défi utilisateur requis) et détecte les attaques par présentation (photos de photos, écrans, masques). Pour obtenir les meilleurs résultats, soumettez un seul visage net, de face et bien éclairé par image.\n\n**Logique de décision.** Tout avertissement entraîne un refus : `status` est `Approved` uniquement lorsque le tableau `warnings` est vide. Un `score` de vivacité inférieur ou égal à `face_liveness_score_decline_threshold` (par défaut `30`) ajoute `LOW_LIVENESS_SCORE` ; une attaque détectée ajoute `LIVENESS_FACE_ATTACK` ; aucun visage trouvé par le modèle de détection du vivant ajoute `NO_FACE_DETECTED` ; aucun âge de visage estimable ajoute `AGE_NOT_DETECTED` (`age_estimation` est `null`) ; un âge estimé inférieur à `age_estimation_decline_threshold` (par défaut `18`) ajoute `AGE_BELOW_MINIMUM`. Pour les âges limites proches de votre seuil, il est recommandé de basculer vers une vérification basée sur un document — l'erreur du modèle augmente pour les visages proches de la limite.\n\n**Facturation.** Chaque réponse `200` consomme un crédit API Estimation de l'âge (déduit du crédit de votre forfait ou du solde de recharge). Lorsque le solde de l'organisation ne peut pas couvrir l'appel, l'endpoint renvoie une erreur `403` pour crédits insuffisants avant tout traitement d'image.\n\n**Persistance de la session (`save_api_request`, par défaut `true`).** Lorsque la valeur est `true`, l'appel est conservé sous forme de session de type API : il apparaît dans la Business Console, le `request_id` renvoyé est un identifiant de session réel que vous pouvez transmettre à `GET /v3/session/{sessionId}/decision/` (le résultat y est exposé dans `liveness_checks[]`, avec `features: [\"AGE_ESTIMATION\"]`), le recadrage du visage et l'image de référence sont stockés, l'embedding facial est ajouté à l'index de visages de votre application (utilisé par la recherche faciale et la détection de doublons), et un webhook `status.updated` est émis. Lorsque la valeur est `false`, rien n'est stocké et `request_id` est un UUID de corrélation unique qui ne peut pas être consulté ultérieurement.\n\n**Sandbox.** Les clés API de sandbox ignorent tout traitement et facturation : après validation de la requête (une entrée malformée renvoie toujours `400`), l'endpoint renvoie un payload fictif statique `Approved` (`age_estimation: 30`, sans avertissements), aucune session n'est conservée et aucun crédit n'est consommé.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou invalides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) — cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes/min par clé API sur tous les endpoints POST/PATCH/DELETE ; tout dépassement renvoie `429`.",
        "operationId": "post_v3age-estimation",
        "x-didit-sdk": {
          "resource": "age_estimation",
          "method": "estimate",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "user_image"
                ],
                "properties": {
                  "user_image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Photo de visage à analyser (par ex. un selfie). Soumettez une seule photo de face avec le visage du sujet clairement visible et bien éclairé. Extensions autorisées : `tiff`, `jpg`, `jpeg`, `png`, `webp` (pas de PDF). Taille maximale de téléversement : **5 MB** (les fichiers plus volumineux sont rejetés avec une erreur `400`). Les images sont automatiquement compressées à ~0,3 MB avant le traitement, de sorte que de très hautes résolutions n'améliorent pas la précision."
                  },
                  "face_liveness_score_decline_threshold": {
                    "type": "number",
                    "format": "float",
                    "default": 30,
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Seuil de détection du vivant (0–100). Un `score` de détection du vivant **inférieur ou égal** à cette valeur ajoute un avertissement `LOW_LIVENESS_SCORE` et refuse la vérification. Augmentez-le pour un anti-usurpation plus strict ; les valeurs en dehors de 0–100 renvoient `400`.",
                    "example": 30
                  },
                  "age_estimation_decline_threshold": {
                    "type": "integer",
                    "default": 18,
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Âge estimé minimum acceptable en années. Un âge estimé **inférieur** à cette valeur ajoute un avertissement `AGE_BELOW_MINIMUM` et refuse la vérification. Définissez `0` pour désactiver la vérification de l'âge (l'appel exécute alors uniquement la détection du vivant + l'estimation de l'âge sans décision basée sur l'âge).",
                    "example": 18
                  },
                  "rotate_image": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lorsque la valeur est `true`, le service teste l'image fournie par incréments de 90 degrés (0, 90, 180, 270) et utilise l'orientation qui produit la meilleure détection faciale — utile pour les captures mobiles sans orientation EXIF. Ajoute de la latence, ne l'activez donc que si vous ne pouvez pas garantir des images dans le bon sens.",
                    "example": false
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Lorsque la valeur est `true` (par défaut), conserve l'appel sous la forme d'une session de type API — visible dans la Business Console, récupérable via `GET /v3/session/{sessionId}/decision/` à l'aide du `request_id` renvoyé, notifiée via un webhook `status.updated`, et avec le visage détecté ajouté à l'index facial de votre application. Lorsque la valeur est `false`, rien n'est stocké et `request_id` est un UUID éphémère servant uniquement à la corrélation des réponses.",
                    "example": true
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Chaîne opaque optionnelle (votre identifiant d'utilisateur interne, e-mail, UUID…) stockée sur la session persistée et renvoyée dans la réponse. Utilisez-la pour corréler les appels d'API avec vos propres enregistrements et pour filtrer les sessions ultérieurement.",
                    "example": "user-123"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Objet JSON optionnel stocké avec la session (lorsque `save_api_request=true`) et renvoyé dans la réponse. Dans les requêtes multipart, envoyez-le sous forme de champ textuel encodé en JSON (par ex. `metadata={\"flow\":\"age-gate\"}`) — il est analysé sous forme d'objet.",
                    "example": {
                      "flow": "age-gate"
                    }
                  }
                }
              },
              "example": {
                "user_image": "(binary JPEG/PNG of the selfie)",
                "face_liveness_score_decline_threshold": 30,
                "age_estimation_decline_threshold": 18,
                "rotate_image": false,
                "save_api_request": true,
                "vendor_data": "user-123",
                "metadata": {
                  "flow": "age-gate"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estimation de l'âge et détection passive du vivant terminées. `age_estimation.age_estimation` est l'âge en années prédit par le modèle pour le plus grand visage détecté (`null` si aucun) ; `age_estimation.score` est le score de détection passive du vivant (0–100) ; `status` est `Approved` uniquement lorsque `warnings` est vide. Une capture de personne mineure ou usurpée renvoie tout de même `200` avec `status: \"Declined\"` : inspectez le corps, pas seulement le code HTTP. Lorsque `save_api_request=true`, `request_id` est l'identifiant de session enregistré.",
            "content": {
              "application/json": {
                "examples": {
                  "Approved": {
                    "summary": "Visage adulte vivant — les deux vérifications ont réussi",
                    "value": {
                      "request_id": "0c40ba43-64ab-4e2e-b4b8-7d1f12f81bc1",
                      "age_estimation": {
                        "status": "Approved",
                        "method": "PASSIVE",
                        "score": 97.5,
                        "user_image": {
                          "entities": [
                            {
                              "age": 27.33,
                              "bbox": [
                                40,
                                40,
                                100,
                                100
                              ],
                              "confidence": 0.7177750468254089,
                              "gender": "male"
                            }
                          ],
                          "best_angle": 0
                        },
                        "age_estimation": 27.33,
                        "warnings": []
                      },
                      "vendor_data": "user-123",
                      "metadata": {
                        "flow": "age-gate"
                      },
                      "created_at": "2026-06-12T02:24:11.512941+00:00"
                    }
                  },
                  "Declined - age below threshold": {
                    "summary": "Âge estimé inférieur à `age_estimation_decline_threshold`",
                    "value": {
                      "request_id": "9be41a6f-2f4e-4f57-92f4-b3a4f6f0a1c2",
                      "age_estimation": {
                        "status": "Declined",
                        "method": "PASSIVE",
                        "score": 95.0,
                        "user_image": {
                          "entities": [
                            {
                              "age": 16.5,
                              "bbox": [
                                40,
                                40,
                                100,
                                100
                              ],
                              "confidence": 0.7177750468254089,
                              "gender": "female"
                            }
                          ],
                          "best_angle": 0
                        },
                        "age_estimation": 16.5,
                        "warnings": [
                          {
                            "risk": "AGE_BELOW_MINIMUM",
                            "feature": "LIVENESS",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Age below minimum",
                            "long_description": "The age of the face is below the minimum age threshold for the application."
                          }
                        ]
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T02:26:40.118332+00:00"
                    }
                  },
                  "Declined - liveness too low": {
                    "summary": "Score de détection du vivant inférieur ou égal au seuil de refus (usurpation possible)",
                    "value": {
                      "request_id": "5f6f2f1f-7c4f-43b9-8d62-0a8f4c2d9e77",
                      "age_estimation": {
                        "status": "Declined",
                        "method": "PASSIVE",
                        "score": 5.0,
                        "user_image": {
                          "entities": [
                            {
                              "age": 25.0,
                              "bbox": [
                                40,
                                40,
                                100,
                                100
                              ],
                              "confidence": 0.7177750468254089,
                              "gender": "male"
                            }
                          ],
                          "best_angle": 0
                        },
                        "age_estimation": 25.0,
                        "warnings": [
                          {
                            "risk": "LOW_LIVENESS_SCORE",
                            "feature": "LIVENESS",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Low liveness score",
                            "long_description": "The liveness check resulted in a low score, indicating potential use of non-live facial representations or poor-quality biometric data."
                          }
                        ]
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T02:27:02.901547+00:00"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "age_estimation": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "Declined"
                          ],
                          "description": "`Approved` lorsqu'aucun avertissement n'a été émis ; `Declined` dans le cas contraire (chaque avertissement généré par cet endpoint entraîne un refus)."
                        },
                        "method": {
                          "type": "string",
                          "enum": [
                            "PASSIVE"
                          ],
                          "description": "Méthode de détection du vivant. Toujours `PASSIVE` sur cet endpoint (image unique, aucun défi utilisateur)."
                        },
                        "score": {
                          "type": "number",
                          "format": "float",
                          "nullable": true,
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Score de détection passive du vivant de 0 à 100 — la confiance du modèle dans le fait que la photo montre une personne vivante. Comparé à `face_liveness_score_decline_threshold` ; à ce niveau ou en dessous, l'appel est refusé avec `LOW_LIVENESS_SCORE`. `null` lorsque le modèle de détection du vivant ne renvoie aucune confiance — l'appel est tout de même refusé avec `LOW_LIVENESS_SCORE` car null est traité comme 0 pour la comparaison avec le seuil.",
                          "example": 97.5
                        },
                        "user_image": {
                          "type": "object",
                          "description": "Résultats de la détection faciale pour l'image analysée.",
                          "properties": {
                            "entities": {
                              "type": "array",
                              "description": "Une entrée par visage détecté. Vide si aucun visage n'a été trouvé (dans ce cas, `age_estimation` est `null` et un avertissement `AGE_NOT_DETECTED` est ajouté).",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "age": {
                                    "type": "number",
                                    "format": "float",
                                    "description": "Âge estimé par le modèle pour ce visage, en années.",
                                    "example": 27.33
                                  },
                                  "bbox": {
                                    "type": "array",
                                    "items": {
                                      "type": "integer"
                                    },
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "description": "Boîte englobante du visage détecté sous forme de coordonnées en pixels `[x_min, y_min, x_max, y_max]` dans l'image traitée.",
                                    "example": [
                                      40,
                                      40,
                                      100,
                                      100
                                    ]
                                  },
                                  "confidence": {
                                    "type": "number",
                                    "format": "float",
                                    "minimum": 0,
                                    "maximum": 1,
                                    "description": "Indice de confiance de la détection faciale (0–1).",
                                    "example": 0.7177750468254089
                                  },
                                  "gender": {
                                    "type": "string",
                                    "description": "Genre prédit par le modèle pour le visage détecté (`male` ou `female`). À titre informatif uniquement.",
                                    "example": "male"
                                  }
                                }
                              }
                            },
                            "best_angle": {
                              "type": "integer",
                              "nullable": true,
                              "description": "Rotation (en degrés : 0, 90, 180 ou 270) ayant produit la meilleure détection de visage. Non nulle uniquement lorsque `rotate_image=true` a corrigé l'orientation.",
                              "example": 0
                            }
                          }
                        },
                        "age_estimation": {
                          "type": "number",
                          "format": "float",
                          "nullable": true,
                          "description": "Âge prédit par le modèle en années pour le **plus grand** visage détecté. `null` lorsqu'aucun âge du visage n'a pu être estimé (un avertissement `AGE_NOT_DETECTED` est ajouté et l'appel est refusé).",
                          "example": 27.33
                        },
                        "warnings": {
                          "type": "array",
                          "description": "Vide en cas d'approbation sans réserve. Toute entrée définit `status` sur `Declined`.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "risk": {
                                "type": "string",
                                "enum": [
                                  "NO_FACE_DETECTED",
                                  "LOW_LIVENESS_SCORE",
                                  "LIVENESS_FACE_ATTACK",
                                  "AGE_NOT_DETECTED",
                                  "AGE_BELOW_MINIMUM"
                                ],
                                "description": "Code de risque lisible par machine. `NO_FACE_DETECTED` — le modèle de détection du vivant n'a trouvé aucun visage ; `LOW_LIVENESS_SCORE` — `score` de détection du vivant inférieur ou égal à `face_liveness_score_decline_threshold` ; `LIVENESS_FACE_ATTACK` — une attaque par présentation (photo/écran/masque) a été détectée ; `AGE_NOT_DETECTED` — aucun âge n'a pu être estimé à partir du visage ; `AGE_BELOW_MINIMUM` — âge estimé inférieur à `age_estimation_decline_threshold`. `NO_FACE_DETECTED` et `LOW_LIVENESS_SCORE` sont mutuellement exclusifs — lorsqu'aucun visage n'est trouvé, seul `NO_FACE_DETECTED` est émis."
                              },
                              "feature": {
                                "type": "string",
                                "enum": [
                                  "LIVENESS"
                                ],
                                "description": "Fonctionnalité ayant émis l'avertissement. Toujours `LIVENESS` sur cet endpoint."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "additionalProperties": true,
                                "description": "Toujours `null` pour les avertissements d'estimation de l'âge."
                              },
                              "log_type": {
                                "type": "string",
                                "enum": [
                                  "error"
                                ],
                                "description": "Gravité. Chaque avertissement produit par cet endpoint est une `error` et définit `status` sur `Declined`."
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Résumé du risque en une ligne, lisible par l'utilisateur."
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication lisible par l'humain du risque."
                              }
                            }
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Écho des `vendor_data` que vous avez envoyées, ou `null`."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Écho de l'objet `metadata` que vous avez envoyé, ou `null`."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Horodatage ISO 8601 (UTC) du moment où la réponse a été générée."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Renvoyée lorsque `user_image` est manquant, dépasse 5 Mo, possède une extension non prise en charge, ou lorsqu'un seuil est hors limites. Le corps est l'enveloppe standard d'erreur de champ de DRF : un tableau de messages par champ en cause.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing user image": {
                    "summary": "`user_image` non inclus dans les données de formulaire",
                    "value": {
                      "user_image": [
                        "No file was submitted."
                      ]
                    }
                  },
                  "Unsupported file extension": {
                    "summary": "Extension de fichier autre que tiff/jpg/jpeg/png/webp",
                    "value": {
                      "user_image": [
                        "File extension “txt” is not allowed. Allowed extensions are: tiff, jpg, jpeg, png, webp."
                      ]
                    }
                  },
                  "File too large": {
                    "summary": "Le téléversement dépasse la limite de 5 MB",
                    "value": {
                      "user_image": [
                        "File size should not exceed 5 MB"
                      ]
                    }
                  },
                  "Threshold out of range": {
                    "summary": "`face_liveness_score_decline_threshold` hors de 0–100",
                    "value": {
                      "face_liveness_score_decline_threshold": [
                        "Ensure this value is less than or equal to 100."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout traitement d'image.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/age-estimation/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'user_image=@./selfie.jpg' \\\n  -F 'age_estimation_decline_threshold=18' \\\n  -F 'face_liveness_score_decline_threshold=30' \\\n  -F 'save_api_request=true' \\\n  -F 'vendor_data=user-123'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.age_estimation.estimate(\n    user_image=open(\"user_image.jpg\", \"rb\"),\n    face_liveness_score_decline_threshold=30.0,\n    age_estimation_decline_threshold=18,\n    rotate_image=False,\n    save_api_request=True,\n    vendor_data=\"user-123\",\n    metadata={\"flow\": \"age-gate\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.ageEstimation.estimate({\n  user_image: await fileFromPath(\"user_image.jpg\"),\n  face_liveness_score_decline_threshold: 30.0,\n  age_estimation_decline_threshold: 18,\n  rotate_image: false,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"age-gate\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.AgeEstimation.Estimate(ctx, didit.AgeEstimationEstimateParams{\n\tUserImage:                         didit.FileFromPath(\"user_image.jpg\"),\n\tFaceLivenessScoreDeclineThreshold: didit.Float(30.0),\n\tAgeEstimationDeclineThreshold:     didit.Int(18),\n\tRotateImage:                       didit.Bool(false),\n\tSaveAPIRequest:                    didit.Bool(true),\n\tVendorData:                        didit.String(\"user-123\"),\n\tMetadata:                          didit.Some(map[string]any{\"flow\": \"age-gate\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.AgeEstimationEstimateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.ageEstimation().estimate(AgeEstimationEstimateParams.builder()\n        .userImage(Path.of(\"user_image.jpg\"))\n        .faceLivenessScoreDeclineThreshold(30.0)\n        .ageEstimationDeclineThreshold(18L)\n        .rotateImage(false)\n        .saveApiRequest(true)\n        .vendorData(\"user-123\")\n        .metadata(Map.of(\"flow\", \"age-gate\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->ageEstimation->estimate([\n    'user_image' => File::fromPath('user_image.jpg'),\n    'face_liveness_score_decline_threshold' => 30.0,\n    'age_estimation_decline_threshold' => 18,\n    'rotate_image' => false,\n    'save_api_request' => true,\n    'vendor_data' => 'user-123',\n    'metadata' => ['flow' => 'age-gate'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.age_estimation.estimate(\n  user_image: Pathname(\"user_image.jpg\"),\n  face_liveness_score_decline_threshold: 30.0,\n  age_estimation_decline_threshold: 18,\n  rotate_image: false,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"age-gate\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.AgeEstimation.EstimateAsync(new AgeEstimationEstimateParams\n{\n    UserImage = FileUpload.FromPath(\"user_image.jpg\"),\n    FaceLivenessScoreDeclineThreshold = 30.0,\n    AgeEstimationDeclineThreshold = 18,\n    RotateImage = false,\n    SaveApiRequest = true,\n    VendorData = \"user-123\",\n    Metadata = new Dictionary<string, object> { [\"flow\"] = \"age-gate\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/poa/": {
      "post": {
        "summary": "Justificatif de domicile (OCR de document + contrôles d'adresse)",
        "description": "Extrayez et validez un justificatif de domicile — factures de services publics, relevés bancaires et documents officiels — en un seul appel. Renvoie l'émetteur, les dates d'émission/d'expiration, le nom du titulaire, l'adresse brute et analysée/géocodée, un `status` `Approved`/`Declined`, ainsi qu'une liste `warnings` expliquant chaque problème détecté.\n\n**Latence.** L'extraction est basée sur des LLM : les appels typiques prennent **5–15 secondes**, et les PDF de plusieurs pages jusqu'à **~30 secondes**. Configurez un délai d'expiration client d'**au moins 45 secondes** et ne réessayez pas avant la fin de l'appel.\n\n**Fonctionnement.** Le document (image ou PDF, jusqu'à 15 Mo ; les PDF chiffrés nécessitent `document_password`) est classé selon un type et un sous-type de document (par exemple `UTILITY_BILL` / `WATER_BILL`), puis l'émetteur, les dates, le nom du titulaire et l'adresse sont extraits grâce à une extraction basée sur des LLM. L'adresse est analysée et géocodée dans `poa_parsed_address`. L'analyse médico-légale PDF/EXIF recherche les altérations — modification après signature numérique, éditeurs PDF connus, manipulation de texte superposé, réexportations suspectes — faisant remonter `SUSPECTED_DOCUMENT_MANIPULATION` ou `DOCUMENT_METADATA_MISMATCH`. Un champ de texte qui a été effacé puis réécrit avec une autre police, lorsque le fichier lui-même ne contient aucune preuve de la modification de son contenu, fait remonter `POA_DOCUMENT_UNPROVEN_TEXT_REPLACEMENT`. L'ancienneté du document est validée par rapport à `poa_document_age_months`, et la langue par rapport à `poa_languages_allowed`. Si vous transmettez `expected_address`, `expected_country` ou `expected_first_name`/`expected_last_name`, les valeurs extraites font l'objet d'une vérification croisée et les non-correspondances sont signalées.\n\n**Logique de décision.** `status` est `Approved` à moins qu'au moins un avertissement n'entraîne un refus. Les échecs critiques entraînent toujours un refus : `MISSING_ADDRESS_INFORMATION`, `POA_DOCUMENT_EXPIRED`, `INVALID_DOCUMENT_TYPE`, `UNABLE_TO_VALIDATE_DOCUMENT_AGE`, ainsi que `UNABLE_TO_EXTRACT_ISSUE_DATE` et `POA_NAME_NOT_DETECTED` (non configurables sur cet endpoint). Cinq groupes de risques sont configurables par requête via les options `poa_*_action` (`DECLINE` ou `NO_ACTION`, ayant toutes `DECLINE` par défaut). `POA_DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION` et `UNPARSABLE_OR_INVALID_ADDRESS` sont informatifs sur cet endpoint et n'entraînent jamais de refus. Un document qui ne peut pas du tout être traité renvoie `400` ; un document lisible mais problématique renvoie `200` avec `status: \"Declined\"` — examinez toujours `poa.status` et `poa.warnings`, pas seulement le code HTTP.\n\n**Facturation.** Chaque réponse `200` consomme un crédit d'API Justificatif de domicile (déduit du crédit de votre forfait ou de votre solde de recharge). Lorsque le solde de l'organisation ne peut pas couvrir l'appel, l'endpoint renvoie `403` avec l'erreur indiquant que les crédits sont insuffisants avant tout traitement de document.\n\n**Persistance de session (`save_api_request`, valeur par défaut `true`).** Lorsque la valeur est `true`, l'appel est conservé sous forme de session de type API : il apparaît dans la Business Console, le document importé est stocké, le `request_id` renvoyé est un véritable identifiant de session que vous pouvez transmettre à `GET /v3/session/{sessionId}/decision/` (la décision expose en outre `document_file` et les données médico-légales de `document_metadata`, que cette réponse omet), et un webhook `status.updated` est émis. Lorsque la valeur est `false`, rien n'est stocké et `request_id` est un UUID de corrélation à usage unique qui ne pourra pas être consulté ultérieurement.\n\n**Sandbox.** Les clés API de sandbox ignorent tout traitement et toute facturation : après la validation de la requête (une entrée malformée renvoie toujours `400`), l'endpoint renvoie un payload fictif statique `Approved` (une facture d'électricité fictive « Sandbox Power Co. »), aucune session n'est conservée et aucun crédit n'est consommé.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou invalides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) — cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes/min par clé API sur l'ensemble des endpoints POST/PATCH/DELETE ; tout dépassement renvoie `429`.\n\nRemarque : `FUTURE_ISSUE_DATE` et `POOR_DOCUMENT_QUALITY` existent dans les sessions de workflow, mais ne sont jamais générés par cet endpoint autonome — un document avec une date future n'est pas automatiquement refusé ici.",
        "operationId": "post_v3poa",
        "x-didit-sdk": {
          "resource": "proof_of_address",
          "method": "verify",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "document"
                ],
                "properties": {
                  "document": {
                    "type": "string",
                    "format": "binary",
                    "description": "Le justificatif de domicile. Extensions autorisées : `tiff`, `jpg`, `jpeg`, `png`, `pdf`, `webp`. Taille maximale de téléversement : **15 MB** (les fichiers plus volumineux sont rejetés avec un code `400`). Les fichiers PDF multipages sont pris en charge (attendez-vous à une latence plus élevée) ; les PDF chiffrés nécessitent `document_password`. Les images sont automatiquement compressées avant le traitement."
                  },
                  "document_password": {
                    "type": "string",
                    "description": "Mot de passe pour déchiffrer `document` lorsqu'il s'agit d'un PDF chiffré. L'envoi d'un PDF chiffré sans mot de passe (ou avec un mot de passe incorrect) renvoie `400`.",
                    "writeOnly": true
                  },
                  "expected_address": {
                    "type": "string",
                    "description": "Adresse à vérifier par rapport au document. Elle est géocodée et comparée à l'adresse extraite ; une discordance (ou une adresse attendue qui ne peut être géocodée/vérifiée) ajoute `ADDRESS_MISMATCH_WITH_PROVIDED`, selon `poa_address_mismatch_action`. La forme géocodée est renvoyée dans `expected_details_formatted_address` / `expected_details_parsed_address`.",
                    "example": "Av. Monseñor Tavella 1291, Salta, Argentina"
                  },
                  "expected_country": {
                    "type": "string",
                    "description": "Pays à vérifier par rapport au document (code ISO 3166-1, par ex. `ARG` ou `AR`). Une discordance avec le pays du document ajoute `POA_COUNTRY_MISMATCH_WITH_PROVIDED`, régi par `poa_address_mismatch_action`.",
                    "example": "ARG"
                  },
                  "expected_first_name": {
                    "type": "string",
                    "description": "Prénom à vérifier par rapport à `name_on_document` (recherche floue, tenant compte de la translittération). Un score inférieur au seuil de correspondance ajoute `NAME_MISMATCH_WITH_PROVIDED`, régi par `poa_address_mismatch_action`.",
                    "example": "Sophia"
                  },
                  "expected_last_name": {
                    "type": "string",
                    "description": "Nom de famille à vérifier par rapport à `name_on_document`, combiné avec `expected_first_name` pour le score de correspondance.",
                    "example": "Martinez"
                  },
                  "poa_languages_allowed": {
                    "type": "string",
                    "description": "Liste séparée par des virgules des langues acceptées pour le document sous forme de codes ISO 639-1 (par ex. `en,es,fr`). En cas d'omission ou si elle est vide, **l'ensemble des 51 langues prises en charge** est accepté. Un document dans une langue hors de cette liste ajoute `UNSUPPORTED_DOCUMENT_LANGUAGE` (régi par `poa_unsupported_language_action`) ; un code inconnu dans la liste renvoie `400` avec l'ensemble complet des codes pris en charge.",
                    "example": "en,es"
                  },
                  "poa_document_age_months": {
                    "type": "string",
                    "description": "Paires `key:value` séparées par des virgules définissant l'âge maximal du document en mois par type de document — clés : `utility_bill`, `bank_statement`, `government_issued_document`, `other_poa_document` ; valeurs : `1`–`120`, ou `-1` pour illimité (pas de vérification d'âge). Valeurs par défaut en cas d'omission : `utility_bill:3,bank_statement:3,government_issued_document:12,other_poa_document:12`. Un document plus ancien que sa limite entraîne un refus avec `POA_DOCUMENT_EXPIRED`. **Attention :** lorsque vous fournissez ce champ, listez *chaque* type accepté — les types omis sont traités comme non acceptés (`POA_DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION` d'ordre informatif) et leur vérification d'âge est ignorée.",
                    "example": "utility_bill:3,bank_statement:6"
                  },
                  "poa_name_mismatch_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Accepté mais **actuellement non appliqué** — les avertissements de non-concordance de nom (`NAME_MISMATCH_WITH_PROVIDED`) suivent `poa_address_mismatch_action` à la place. Définissez `poa_address_mismatch_action` pour contrôler à la fois le comportement de non-concordance de nom et d'adresse."
                  },
                  "poa_document_issues_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Ce qu'il faut faire en cas de problème d'intégrité de fichier — en pratique, seul `DOCUMENT_METADATA_MISMATCH` est produit par cet endpoint."
                  },
                  "poa_document_authenticity_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Ce qu'il faut faire lorsqu'une manipulation de document est suspectée (`SUSPECTED_DOCUMENT_MANIPULATION`) — par exemple si le PDF a été modifié après signature numérique, traité par un éditeur PDF connu, présente une manipulation de texte superposé ou des dates EXIF incohérentes. Régit également `POA_DOCUMENT_UNPROVEN_TEXT_REPLACEMENT` (un champ de texte retapé dont le fichier ne peut prouver la modification ou l'absence de modification) : `DECLINE` le refuse également, `NO_ACTION` le conserve comme un avertissement."
                  },
                  "poa_unsupported_language_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Que faire lorsque la langue du document n'appartient pas à `poa_languages_allowed` (`UNSUPPORTED_DOCUMENT_LANGUAGE`)."
                  },
                  "poa_address_mismatch_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Que faire lorsque les détails extraits ne correspondent pas aux champs `expected_*` : `ADDRESS_MISMATCH_WITH_PROVIDED`, `NAME_MISMATCH_WITH_PROVIDED` et `POA_COUNTRY_MISMATCH_WITH_PROVIDED` suivent tous cette action."
                  },
                  "poa_issuer_not_identified_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Ce qu'il faut faire lorsqu'aucune entreprise ou organisation émettrice ne peut être identifiée sur le document (`ISSUER_NOT_IDENTIFIED`)."
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Lorsque la valeur est `true` (par défaut), conserve l'appel sous la forme d'une session de type API — visible dans la Business Console, récupérable via `GET /v3/session/{sessionId}/decision/` à l'aide du `request_id` renvoyé, notifiée via un webhook `status.updated`, et avec le document importé stocké. Lorsque la valeur est `false`, rien n'est stocké et `request_id` est un UUID éphémère servant uniquement à la corrélation des réponses.",
                    "example": true
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Chaîne opaque optionnelle (votre identifiant d'utilisateur interne, e-mail, UUID…) stockée sur la session persistée et renvoyée dans la réponse. Utilisez-la pour corréler les appels d'API avec vos propres enregistrements et pour filtrer les sessions ultérieurement.",
                    "example": "user-123"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Objet JSON optionnel stocké avec la session (lorsque `save_api_request=true`) et renvoyé dans la réponse. Dans les requêtes multipart, envoyez-le sous forme de champ textuel encodé en JSON (par ex. `metadata={\"flow\":\"onboarding\"}`) — il est analysé sous forme d'objet.",
                    "example": {
                      "flow": "onboarding"
                    }
                  }
                }
              },
              "example": {
                "document": "(binary JPEG/PNG/PDF of the utility bill or bank statement)",
                "expected_address": "Av. Monseñor Tavella 1291, Salta, Argentina",
                "expected_country": "ARG",
                "expected_first_name": "Sophia",
                "expected_last_name": "Martinez",
                "poa_languages_allowed": "en,es",
                "save_api_request": true,
                "vendor_data": "user-123"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document traité. `poa.status` est `Approved` ou `Declined` ; chaque problème détecté est détaillé dans `poa.warnings`. Un document expiré, non concordant ou suspect renvoie tout de même `200` avec `status: \"Declined\"` — inspectez le corps de la réponse, pas seulement le code HTTP. Lorsque `save_api_request=true`, `request_id` est l'identifiant de la session enregistrée.",
            "content": {
              "application/json": {
                "examples": {
                  "Approved": {
                    "summary": "Facture de services publics lue clairement, aucune vérification des détails attendus",
                    "value": {
                      "request_id": "4b523a8d-ed32-45e4-8aa8-a89eda459d88",
                      "poa": {
                        "issuing_state": "ARG",
                        "document_type": "UTILITY_BILL",
                        "document_subtype": "WATER_BILL",
                        "document_language": "es",
                        "issuer": "Aguas del Norte",
                        "issue_date": "2026-04-10",
                        "expiration_date": null,
                        "poa_address": "AVDA. MONSEÑOR TAVELLA N° 1291, B° VILLA LAVALLE CP: 4400, CAPITAL - SALTA",
                        "poa_formatted_address": "Av. Monseñor Tavella 1291 b, A4400 Salta, Argentina",
                        "poa_parsed_address": {
                          "street_1": "Avenida Monseñor Tavella 1291",
                          "street_2": "b",
                          "city": "Salta",
                          "region": "Salta",
                          "country": "AR",
                          "postal_code": "A4400",
                          "document_location": {
                            "latitude": -24.8208682,
                            "longitude": -65.4130954
                          }
                        },
                        "expected_details_address": null,
                        "expected_details_formatted_address": null,
                        "expected_details_parsed_address": null,
                        "name_on_document": "OESTE EMBOTELLADORA S.A.",
                        "extra_fields": {
                          "bank_account_number": null,
                          "bank_iban": null,
                          "bank_sort_code": null,
                          "bank_routing_number": null,
                          "bank_swift_bic": null,
                          "bank_branch_name": null,
                          "bank_branch_address": null,
                          "document_phone_number": null,
                          "additional_names": [
                            "LA EMBOTELLADORA DEL NORTE SA"
                          ]
                        },
                        "detected_codes": [
                          {
                            "type": "QR_CODE",
                            "page_number": 1,
                            "position": [
                              [
                                820,
                                1120
                              ],
                              [
                                1002,
                                1120
                              ],
                              [
                                1002,
                                1302
                              ],
                              [
                                820,
                                1302
                              ]
                            ],
                            "x": 820,
                            "y": 1120,
                            "width": 182,
                            "height": 182,
                            "page_width": 1190,
                            "page_height": 1684,
                            "raw_payload": "aHR0cHM6Ly9hZ3Vhc2RlbG5vcnRlLmNvbS9mYWN0dXJhLzk5ODgxMQ==",
                            "parsed_payload": "https://aguasdelnorte.com/factura/998811"
                          },
                          {
                            "type": "CODE_128",
                            "page_number": 1,
                            "position": [
                              [
                                112,
                                1480
                              ],
                              [
                                560,
                                1480
                              ],
                              [
                                560,
                                1540
                              ],
                              [
                                112,
                                1540
                              ]
                            ],
                            "x": 112,
                            "y": 1480,
                            "width": 448,
                            "height": 60,
                            "page_width": 1190,
                            "page_height": 1684,
                            "raw_payload": "MDA5OTg4MTEwMDA0Mg==",
                            "parsed_payload": "0099881100042"
                          }
                        ],
                        "status": "Approved",
                        "warnings": []
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T02:29:02.439655+00:00"
                    }
                  },
                  "Declined - document too old": {
                    "summary": "Date de délivrance antérieure à l'ancienneté autorisée par `poa_document_age_months`",
                    "value": {
                      "request_id": "f61681b8-9422-4378-ac3e-04c6a247fb45",
                      "poa": {
                        "issuing_state": "ARG",
                        "document_type": "UTILITY_BILL",
                        "document_subtype": "WATER_BILL",
                        "document_language": "es",
                        "issuer": "Aguas del Norte",
                        "issue_date": "2021-02-10",
                        "expiration_date": null,
                        "poa_address": "AVDA. MONSEÑOR TAVELLA N° 1291, B° VILLA LAVALLE CP: 4400, CAPITAL - SALTA",
                        "poa_formatted_address": "Av. Monseñor Tavella 1291 b, A4400 Salta, Argentina",
                        "poa_parsed_address": {
                          "street_1": "Avenida Monseñor Tavella 1291",
                          "street_2": "b",
                          "city": "Salta",
                          "region": "Salta",
                          "country": "AR",
                          "postal_code": "A4400",
                          "document_location": {
                            "latitude": -24.8208682,
                            "longitude": -65.4130954
                          }
                        },
                        "expected_details_address": null,
                        "expected_details_formatted_address": null,
                        "expected_details_parsed_address": null,
                        "name_on_document": "OESTE EMBOTELLADORA S.A.",
                        "extra_fields": {
                          "bank_account_number": null,
                          "bank_iban": null,
                          "bank_sort_code": null,
                          "bank_routing_number": null,
                          "bank_swift_bic": null,
                          "bank_branch_name": null,
                          "bank_branch_address": null,
                          "document_phone_number": null,
                          "additional_names": [
                            "LA EMBOTELLADORA DEL NORTE SA"
                          ]
                        },
                        "status": "Declined",
                        "warnings": [
                          {
                            "risk": "POA_DOCUMENT_EXPIRED",
                            "feature": "PROOF_OF_ADDRESS",
                            "additional_data": {
                              "expiration_reason": "age_window",
                              "max_age_months": 3,
                              "document_subtype": "WATER_BILL",
                              "document_type": "UTILITY_BILL",
                              "issue_date": "2021-02-10"
                            },
                            "log_type": "error",
                            "short_description": "Document expired",
                            "long_description": "The submitted document is older than the maximum accepted age of 3 months from its issue date, which exceeds the acceptable time period for validity."
                          }
                        ]
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T02:23:02.165493+00:00"
                    }
                  },
                  "Declined - name mismatch": {
                    "summary": "`expected_first_name`/`expected_last_name` ne correspondent pas à `name_on_document`",
                    "value": {
                      "request_id": "0a7f2f9c-58f1-4b8e-b1e3-2f6f9d4f7a21",
                      "poa": {
                        "issuing_state": "ARG",
                        "document_type": "UTILITY_BILL",
                        "document_subtype": "WATER_BILL",
                        "document_language": "es",
                        "issuer": "Aguas del Norte",
                        "issue_date": "2021-02-10",
                        "expiration_date": null,
                        "poa_address": "AVDA. MONSEÑOR TAVELLA N° 1291, B° VILLA LAVALLE CP: 4400, CAPITAL - SALTA",
                        "poa_formatted_address": "Av. Monseñor Tavella 1291 b, A4400 Salta, Argentina",
                        "poa_parsed_address": {
                          "street_1": "Avenida Monseñor Tavella 1291",
                          "street_2": "b",
                          "city": "Salta",
                          "region": "Salta",
                          "country": "AR",
                          "postal_code": "A4400",
                          "document_location": {
                            "latitude": -24.8208682,
                            "longitude": -65.4130954
                          }
                        },
                        "expected_details_address": null,
                        "expected_details_formatted_address": null,
                        "expected_details_parsed_address": null,
                        "name_on_document": "OESTE EMBOTELLADORA S.A.",
                        "extra_fields": {
                          "bank_account_number": null,
                          "bank_iban": null,
                          "bank_sort_code": null,
                          "bank_routing_number": null,
                          "bank_swift_bic": null,
                          "bank_branch_name": null,
                          "bank_branch_address": null,
                          "document_phone_number": null,
                          "additional_names": [
                            "LA EMBOTELLADORA DEL NORTE SA"
                          ]
                        },
                        "status": "Declined",
                        "warnings": [
                          {
                            "risk": "NAME_MISMATCH_WITH_PROVIDED",
                            "feature": "PROOF_OF_ADDRESS",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Name mismatch with provided information",
                            "long_description": "The full name on the document does not match the name from the user's verified identity documents, or the full name sent by API."
                          }
                        ]
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T02:27:21.330172+00:00"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "poa": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "Declined"
                          ],
                          "description": "`Approved` lorsqu'aucun avertissement n'aboutit à un refus ; `Declined` dans le cas contraire — la liste `warnings` en explique la raison."
                        },
                        "issuing_state": {
                          "type": "string",
                          "nullable": true,
                          "description": "Pays dans lequel le document a été délivré, tel qu'extrait du document — généralement ISO 3166-1 alpha-3 (par ex. `ARG`).",
                          "example": "ARG"
                        },
                        "document_type": {
                          "type": "string",
                          "enum": [
                            "UTILITY_BILL",
                            "BANK_STATEMENT",
                            "GOVERNMENT_ISSUED_DOCUMENT",
                            "OTHER_POA_DOCUMENT",
                            "UNKNOWN"
                          ],
                          "description": "Catégorie de document détectée. `UNKNOWN` signifie que le document n'a pas pu être classé comme un Justificatif de domicile acceptable et entraîne un refus automatique avec `INVALID_DOCUMENT_TYPE`. Jamais null — les échecs de classification basculent sur `UNKNOWN`."
                        },
                        "document_subtype": {
                          "type": "string",
                          "description": "Classification plus détaillée au sein de `document_type` — par ex. `ELECTRICITY_BILL`, `WATER_BILL`, `GAS_BILL`, `INTERNET_BILL`, `PHONE_BILL` (factures de services publics) ; `ACCOUNT_STATEMENT`, `CREDIT_CARD_STATEMENT` (relevés bancaires) ; `TAX_ASSESSMENT`, `RESIDENCY_CERTIFICATE` (documents gouvernementaux). `UNKNOWN` lorsqu'aucun sous-type n'a pu être déterminé. Jamais null — les échecs de classification se rabattent sur `UNKNOWN`.",
                          "example": "WATER_BILL"
                        },
                        "document_language": {
                          "type": "string",
                          "nullable": true,
                          "description": "Langue du document détectée (ISO 639-1).",
                          "example": "es"
                        },
                        "issuer": {
                          "type": "string",
                          "nullable": true,
                          "description": "Entreprise ou organisation ayant émis le document. `null` ajoute `ISSUER_NOT_IDENTIFIED`.",
                          "example": "Aguas del Norte"
                        },
                        "issue_date": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "description": "Date de délivrance du document (`YYYY-MM-DD`). `null` lorsqu'elle n'a pas pu être extraite — cela entraîne un refus avec `UNABLE_TO_EXTRACT_ISSUE_DATE` sur cet endpoint.",
                          "example": "2021-02-10"
                        },
                        "expiration_date": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "description": "Date d'expiration/de validité explicite imprimée sur le document, le cas échéant. Indépendante de la vérification de l'ancienneté `poa_document_age_months`."
                        },
                        "poa_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Adresse exactement telle qu'elle est imprimée sur le document. `null` entraîne un refus automatique avec `MISSING_ADDRESS_INFORMATION`."
                        },
                        "poa_formatted_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Version géocodée et normalisée de `poa_address`.",
                          "example": "Av. Monseñor Tavella 1291 b, A4400 Salta, Argentina"
                        },
                        "poa_parsed_address": {
                          "type": "object",
                          "nullable": true,
                          "description": "Détail structuré et géocodé de l'adresse du document. `null` si l'adresse n'a pas pu être analysée.",
                          "properties": {
                            "street_1": {
                              "type": "string",
                              "nullable": true,
                              "example": "Avenida Monseñor Tavella 1291"
                            },
                            "street_2": {
                              "type": "string",
                              "nullable": true
                            },
                            "city": {
                              "type": "string",
                              "nullable": true,
                              "example": "Salta"
                            },
                            "region": {
                              "type": "string",
                              "nullable": true,
                              "example": "Salta"
                            },
                            "country": {
                              "type": "string",
                              "nullable": true,
                              "description": "Code pays ISO 3166-1 alpha-2.",
                              "example": "AR"
                            },
                            "postal_code": {
                              "type": "string",
                              "nullable": true,
                              "example": "A4400"
                            },
                            "document_location": {
                              "type": "object",
                              "nullable": true,
                              "properties": {
                                "latitude": {
                                  "type": "number"
                                },
                                "longitude": {
                                  "type": "number"
                                }
                              },
                              "description": "Coordonnées géocodées de l'adresse figurant sur le document."
                            }
                          }
                        },
                        "expected_details_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Écho de l'`expected_address` que vous avez envoyée, ou `null`."
                        },
                        "expected_details_formatted_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Version géocodée et normalisée de `expected_address` ; `null` lorsqu'elle n'est pas fournie ou n'est pas géocodable."
                        },
                        "expected_details_parsed_address": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true,
                          "description": "Résultat complet de géocodage pour `expected_address` (rue/ville/région/pays/code postal plus la sortie brute du géocodeur et un indicateur `is_verified`). `null` lorsque `expected_address` n'a pas été fourni."
                        },
                        "name_on_document": {
                          "type": "string",
                          "nullable": true,
                          "description": "Nom du titulaire principal extrait du document ; comparé à `expected_first_name`/`expected_last_name` lorsqu'ils sont fournis. `null` refuse avec `POA_NAME_NOT_DETECTED` sur cet endpoint.",
                          "example": "OESTE EMBOTELLADORA S.A."
                        },
                        "extra_fields": {
                          "type": "object",
                          "description": "Champs supplémentaires spécifiques au document. Les champs bancaires sont renseignés pour les relevés bancaires lorsqu'ils figurent sur le document ; `null` dans le cas contraire.",
                          "properties": {
                            "bank_account_number": {
                              "type": "string",
                              "nullable": true
                            },
                            "bank_iban": {
                              "type": "string",
                              "nullable": true
                            },
                            "bank_sort_code": {
                              "type": "string",
                              "nullable": true
                            },
                            "bank_routing_number": {
                              "type": "string",
                              "nullable": true
                            },
                            "bank_swift_bic": {
                              "type": "string",
                              "nullable": true
                            },
                            "bank_branch_name": {
                              "type": "string",
                              "nullable": true
                            },
                            "bank_branch_address": {
                              "type": "string",
                              "nullable": true
                            },
                            "document_phone_number": {
                              "type": "string",
                              "nullable": true,
                              "description": "Numéro de téléphone de contact imprimé sur le document."
                            },
                            "additional_names": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Autres noms de titulaires trouvés sur le document (par ex. cotitulaires de compte, anciens noms de compte)."
                            }
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "description": "Vide en cas d'approbation sans réserve. Chaque entrée explique un risque détecté ; les entrées avec `log_type: \"error\"` définissent `status` sur `Declined`.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "risk": {
                                "type": "string",
                                "description": "Code de risque lisible par machine. Entraînant toujours un refus : `MISSING_ADDRESS_INFORMATION`, `POA_DOCUMENT_EXPIRED`, `INVALID_DOCUMENT_TYPE`, `UNABLE_TO_VALIDATE_DOCUMENT_AGE`, ainsi que `UNABLE_TO_EXTRACT_ISSUE_DATE` et `POA_NAME_NOT_DETECTED` (configurés de façon fixe pour refuser sur cet endpoint). Régis par les options de requête : `NAME_MISMATCH_WITH_PROVIDED` / `ADDRESS_MISMATCH_WITH_PROVIDED` / `POA_COUNTRY_MISMATCH_WITH_PROVIDED` (`poa_address_mismatch_action`), `POOR_DOCUMENT_QUALITY` (jamais généré par cet endpoint) / `DOCUMENT_METADATA_MISMATCH` (`poa_document_issues_action`), `SUSPECTED_DOCUMENT_MANIPULATION` et `POA_DOCUMENT_UNPROVEN_TEXT_REPLACEMENT` (`poa_document_authenticity_action`), `UNSUPPORTED_DOCUMENT_LANGUAGE` (`poa_unsupported_language_action`), `ISSUER_NOT_IDENTIFIED` (`poa_issuer_not_identified_action`). Informatifs sur cet endpoint : `POA_DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION`, `UNPARSABLE_OR_INVALID_ADDRESS`.",
                                "example": "POA_DOCUMENT_EXPIRED"
                              },
                              "feature": {
                                "type": "string",
                                "enum": [
                                  "PROOF_OF_ADDRESS"
                                ],
                                "description": "Fonctionnalité ayant émis l'avertissement. Toujours `PROOF_OF_ADDRESS` sur cet endpoint."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "additionalProperties": true,
                                "description": "Contexte supplémentaire pour certains risques — par ex. `POA_DOCUMENT_EXPIRED` inclut `expiration_reason` (`printed_expiration` ou `age_window`), `document_type`, `document_subtype` et `issue_date`, ainsi que `expiration_date` pour le chemin `printed_expiration` ou `max_age_months` pour le chemin `age_window` ; `SUSPECTED_DOCUMENT_MANIPULATION` inclut `reason` et `detection_method` ; `POA_DOCUMENT_UNPROVEN_TEXT_REPLACEMENT` inclut `reason`, `detection_method` (`unproven_text_replacement`), `replaced_text`, `manipulated_regions` et `manipulated_blocks`. `null` pour la plupart des risques."
                              },
                              "log_type": {
                                "type": "string",
                                "enum": [
                                  "error",
                                  "information"
                                ],
                                "description": "Gravité. Les avertissements `error` font passer `status` à `Declined` ; les entrées `information` sont indicatives et ne refusent jamais d'elles-mêmes. (`warning` n'est pas produit par cet endpoint — ses options acceptent uniquement `DECLINE` ou `NO_ACTION`.)"
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Résumé du risque en une ligne, lisible par l'utilisateur."
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication lisible par l'humain du risque."
                              }
                            }
                          }
                        },
                        "detected_codes": {
                          "type": "array",
                          "description": "Codes QR et codes-barres détectés sur chaque page traitée du document. Vide si aucun n'est trouvé. Un code QR localisé mais indécodable a `parsed_payload: null`.",
                          "items": {
                            "$ref": "#/components/schemas/DocumentAIDetectedCode"
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Écho des `vendor_data` que vous avez envoyées, ou `null`."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Écho de l'objet `metadata` que vous avez envoyé, ou `null`."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Horodatage ISO 8601 (UTC) du moment où la réponse a été générée."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation ou de traitement. Les problèmes au niveau des champs renvoient l'enveloppe standard de DRF (un tableau de messages par champ concerné). Les problèmes de PDF chiffré renvoient `{\"detail\": ...}`. Un document que le pipeline d'extraction ne peut pas traiter renvoie `{\"error\": [\"Error extracting POA information\"]}`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing document": {
                    "summary": "`document` n'est pas inclus dans les données du formulaire",
                    "value": {
                      "document": [
                        "No file was submitted."
                      ]
                    }
                  },
                  "Unsupported file extension": {
                    "summary": "Extension de fichier autre que tiff/jpg/jpeg/png/pdf/webp",
                    "value": {
                      "document": [
                        "File extension “txt” is not allowed. Allowed extensions are: tiff, jpg, jpeg, png, pdf, webp."
                      ]
                    }
                  },
                  "File too large": {
                    "summary": "Le téléversement dépasse la limite de 15 MB",
                    "value": {
                      "document": [
                        "File size should not exceed 15 MB"
                      ]
                    }
                  },
                  "Encrypted PDF": {
                    "summary": "PDF téléversé sans le mot de passe requis",
                    "value": {
                      "detail": "The PDF is encrypted. Please upload a decrypted PDF or a photo instead."
                    }
                  },
                  "Wrong PDF password": {
                    "summary": "`document_password` ne déchiffre pas le PDF",
                    "value": {
                      "detail": "The PDF password is incorrect. Please provide the correct password."
                    }
                  },
                  "Invalid language code": {
                    "summary": "`poa_languages_allowed` contient un code non pris en charge",
                    "value": {
                      "poa_languages_allowed": [
                        "Invalid language code: 'xx'. Must be one of the supported languages: ['ar', 'bn', 'hy', 'bg', 'bs', 'ca', 'cnr', 'sq', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'et', 'fi', 'fr', 'ka', 'kk', 'de', 'el', 'he', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ky', 'lv', 'lt', 'mk', 'mn', 'ms', 'no', 'fa', 'pl', 'pt', 'ro', 'ru', 'sr', 'sk', 'sl', 'so', 'es', 'sv', 'th', 'tr', 'uk', 'uz', 'vi']."
                      ]
                    }
                  },
                  "Invalid document age value": {
                    "summary": "valeur de `poa_document_age_months` en dehors de la plage 1–120 / -1",
                    "value": {
                      "poa_document_age_months": [
                        "Invalid integer value for 'utility_bill': '999'. Must be -1 (unlimited) or a positive integer between 1 and 120."
                      ]
                    }
                  },
                  "Extraction failure": {
                    "summary": "Le document n'a pas pu être traité par le pipeline d'extraction",
                    "value": {
                      "error": [
                        "Error extracting POA information"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout traitement de document.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/DocumentProcessingBusy"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/poa/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'document=@./utility-bill.pdf' \\\n  -F 'expected_address=Av. Monseñor Tavella 1291, Salta, Argentina' \\\n  -F 'expected_country=ARG' \\\n  -F 'expected_first_name=Sophia' \\\n  -F 'expected_last_name=Martinez' \\\n  -F 'poa_languages_allowed=en,es' \\\n  -F 'vendor_data=user-123' \\\n  --max-time 45"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.proof_of_address.verify(\n    document=open(\"document.pdf\", \"rb\"),\n    expected_address=\"Av. Monseñor Tavella 1291, Salta, Argentina\",\n    expected_country=\"ARG\",\n    expected_first_name=\"Sophia\",\n    expected_last_name=\"Martinez\",\n    poa_languages_allowed=\"en,es\",\n    save_api_request=True,\n    vendor_data=\"user-123\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.proofOfAddress.verify({\n  document: await fileFromPath(\"document.pdf\"),\n  expected_address: \"Av. Monseñor Tavella 1291, Salta, Argentina\",\n  expected_country: \"ARG\",\n  expected_first_name: \"Sophia\",\n  expected_last_name: \"Martinez\",\n  poa_languages_allowed: \"en,es\",\n  save_api_request: true,\n  vendor_data: \"user-123\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.ProofOfAddress.Verify(ctx, didit.ProofOfAddressVerifyParams{\n\tDocument:            didit.FileFromPath(\"document.pdf\"),\n\tExpectedAddress:     didit.String(\"Av. Monseñor Tavella 1291, Salta, Argentina\"),\n\tExpectedCountry:     didit.String(\"ARG\"),\n\tExpectedFirstName:   didit.String(\"Sophia\"),\n\tExpectedLastName:    didit.String(\"Martinez\"),\n\tPOALanguagesAllowed: didit.String(\"en,es\"),\n\tSaveAPIRequest:      didit.Bool(true),\n\tVendorData:          didit.String(\"user-123\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\nimport me.didit.types.ProofOfAddressVerifyParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.proofOfAddress().verify(ProofOfAddressVerifyParams.builder()\n        .document(Path.of(\"document.pdf\"))\n        .expectedAddress(\"Av. Monseñor Tavella 1291, Salta, Argentina\")\n        .expectedCountry(\"ARG\")\n        .expectedFirstName(\"Sophia\")\n        .expectedLastName(\"Martinez\")\n        .poaLanguagesAllowed(\"en,es\")\n        .saveApiRequest(true)\n        .vendorData(\"user-123\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->proofOfAddress->verify([\n    'document' => File::fromPath('document.pdf'),\n    'expected_address' => 'Av. Monseñor Tavella 1291, Salta, Argentina',\n    'expected_country' => 'ARG',\n    'expected_first_name' => 'Sophia',\n    'expected_last_name' => 'Martinez',\n    'poa_languages_allowed' => 'en,es',\n    'save_api_request' => true,\n    'vendor_data' => 'user-123',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.proof_of_address.verify(\n  document: Pathname(\"document.pdf\"),\n  expected_address: \"Av. Monseñor Tavella 1291, Salta, Argentina\",\n  expected_country: \"ARG\",\n  expected_first_name: \"Sophia\",\n  expected_last_name: \"Martinez\",\n  poa_languages_allowed: \"en,es\",\n  save_api_request: true,\n  vendor_data: \"user-123\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.ProofOfAddress.VerifyAsync(new ProofOfAddressVerifyParams\n{\n    Document = FileUpload.FromPath(\"document.pdf\"),\n    ExpectedAddress = \"Av. Monseñor Tavella 1291, Salta, Argentina\",\n    ExpectedCountry = \"ARG\",\n    ExpectedFirstName = \"Sophia\",\n    ExpectedLastName = \"Martinez\",\n    PoaLanguagesAllowed = \"en,es\",\n    SaveApiRequest = true,\n    VendorData = \"user-123\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/document-ai/": {
      "post": {
        "summary": "Document AI (extraction de champs personnalisés + vérifications de falsification)",
        "description": "Extrayez les champs que **vous** définissez à partir de n'importe quel document justificatif — fiches de paie, justificatifs de fonds, attestations d'origine du patrimoine, avis d'imposition, contrats, factures — en un seul appel. Envoyez le fichier accompagné d'une définition `fields` (clé, nom, instruction d'extraction, type) et recevez des valeurs typées (`text`, `number`, `date` sous la forme `YYYY-MM-DD`), un score facultatif de correspondance de nom avec la personne ou l'entreprise attendue, des signaux d'altération PDF/EXIF, un `status` `Approved`/`Declined`/`In Review` et une liste `warnings` détaillant chaque problème détecté. Il s'agit de l'équivalent serveur à serveur de l'étape de workflow Document AI hébergée (voir `/core-technology/document-ai/overview`) ; il utilise le modèle d'extraction par défaut de Didit et ne permet pas de choisir le fournisseur.\n\n**Latence.** L'extraction repose sur un LLM : les appels classiques prennent **5 à 15 secondes**, les PDF multipages jusqu'à **~30 secondes**. Configurez un délai d'expiration client d'**au moins 45 secondes** et ne réessayez pas avant la fin de l'appel.\n\n**Format de la requête.** `multipart/form-data` uniquement. `fields` est **une chaîne de tableau encodée en JSON** (1 à 30 éléments, 16 Ko au maximum) ; les tableaux de formulaire au format crochets sont rejetés avec un code `400`. Chaque élément est `{key, name, instruction, type, required, is_full_name}` — `key` est la clé JSON retournée (`^[a-z0-9_]{1,64}$`, unique), `instruction` indique au modèle ce qu'il doit lire, `type` vaut `text` (par défaut) | `number` | `date`, `required` déclenche `DOCUMENT_AI_MISSING_REQUIRED_FIELDS` lorsque la valeur ne peut pas être lue, et au maximum un champ peut définir `is_full_name: true` pour indiquer la valeur comparée au nom attendu.\n\n**Correspondance de nom.** Transmettez `expected_first_name` + `expected_last_name` (personne physique) **ou** `expected_company_name` (+ facultatif `expected_company_country`) — mais pas les deux. La valeur du champ `is_full_name` (ou, si aucun n'est défini, le premier champ texte dont la clé ressemble à un nom) fait l'objet d'une comparaison approximative ; `name_match_score` (0–100) et `name_on_document` sont toujours retournés lorsque les deux côtés sont présents, et un score inférieur à `document_ai_name_match_score_threshold` (80 par défaut) ajoute `DOCUMENT_AI_NAME_MISMATCH`, régi par `document_ai_name_mismatch_action`.\n\n**Logique de décision.** Chaque risque est associé à une action configurable : `DECLINE` → `status: \"Declined\"`, `REVIEW` → `status: \"In Review\"`, `NO_ACTION` → informatif uniquement. Les valeurs par défaut reflètent l'étape de workflow : document illisible `REVIEW`, champs obligatoires manquants `REVIEW`, manipulation suspectée `DECLINE`, non-correspondance de nom `NO_ACTION`, fichier non pris en charge `REVIEW`. Un document qui ne peut pas du tout être traité renvoie `400` ; un document lisible mais problématique renvoie `200` avec `Declined`/`In Review` — vérifiez toujours `document_ai.status` et `document_ai.warnings`, et pas seulement le code HTTP.\n\n**Facturation.** Chaque réponse `200` consomme un crédit d'API Document AI — **$0.20** par document au tarif catalogue, déduit du crédit de votre forfait ou de votre solde de recharge. Lorsque le solde de l'organisation ne permet pas de couvrir l'appel, l'endpoint renvoie `403` avant tout traitement. Les clés API sandbox renvoient une réponse fictive déterministe et ne sont pas facturées.\n\n**Persistance.** Avec `save_api_request=true` (par défaut), l'appel est enregistré sous forme de session de type API : le document, les valeurs extraites, les définitions de champs et l'instantané de correspondance de nom sont conservés, la session apparaît dans la Business Console, et `request_id` fonctionne avec `GET /v3/session/{sessionId}/decision/`.",
        "operationId": "post_v3document-ai",
        "x-didit-sdk": {
          "resource": "document_ai",
          "method": "analyze",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "document",
                  "fields"
                ],
                "properties": {
                  "document": {
                    "type": "string",
                    "format": "binary",
                    "description": "Le document à lire. Extensions autorisées : `tiff`, `jpg`, `jpeg`, `png`, `pdf`, `webp`, `zip`. Taille maximale de téléversement : **30 MB** (les fichiers plus volumineux sont rejetés avec une erreur `400`). Les fichiers PDF multipages sont pris en charge (prévoyez une latence plus élevée) ; les PDF chiffrés sont rejetés avec une erreur `400`. Les images sont automatiquement compressées avant le traitement."
                  },
                  "fields": {
                    "type": "string",
                    "description": "Une chaîne de tableau encodée en JSON avec **1–30** définitions de champs (maximum 16 KB). Chaque élément : `key` (obligatoire, `^[a-z0-9_]{1,64}$`, unique — la clé renvoyée dans `extracted_data`), `name` (≤ 100 caractères, affiché dans les messages), `instruction` (≤ 500 caractères, ce que le modèle doit lire), `type` (`text` par défaut | `number` | `date`), `required` (booléen, par défaut `false`), `is_full_name` (booléen, par défaut `false`, au maximum un par requête). Les tableaux de formulaires de type crochets, le JSON invalide, les clés dupliquées ou plus d'un `is_full_name` renvoient `400` avant tout traitement ou facturation.",
                    "example": "[{\"key\": \"employer_name\", \"name\": \"Employer name\", \"instruction\": \"The employer or company issuing the payslip.\", \"type\": \"text\", \"required\": true, \"is_full_name\": false}, {\"key\": \"employee_name\", \"name\": \"Employee name\", \"instruction\": \"The full name of the employee as printed on the payslip.\", \"type\": \"text\", \"required\": true, \"is_full_name\": true}, {\"key\": \"net_pay\", \"name\": \"Net pay\", \"instruction\": \"The net amount paid to the employee for the period.\", \"type\": \"number\", \"required\": true, \"is_full_name\": false}, {\"key\": \"pay_date\", \"name\": \"Pay date\", \"instruction\": \"The payment date shown on the payslip.\", \"type\": \"date\", \"required\": false, \"is_full_name\": false}]"
                  },
                  "expected_first_name": {
                    "type": "string",
                    "description": "Prénom à vérifier par rapport au champ du nom du document (recherche floue, tenant compte de la translittération). À utiliser conjointement avec `expected_last_name` ; ne peut pas être combiné avec `expected_company_name`.",
                    "example": "Sophia"
                  },
                  "expected_last_name": {
                    "type": "string",
                    "description": "Nom de famille à vérifier par rapport au champ du nom du document, combiné avec `expected_first_name` pour `name_match_score`.",
                    "example": "Martinez"
                  },
                  "expected_company_name": {
                    "type": "string",
                    "description": "Nom de l'entreprise à vérifier par rapport au champ de nom du document (pour les documents d'entreprise). Ne peut pas être combiné avec `expected_first_name` / `expected_last_name` (aucun exemple de valeur fourni intentionnellement — l'exemple de requête généré utilise les champs de personne physique ; remplacez-les par celui-ci lors de la vérification d'un document d'entreprise)."
                  },
                  "expected_company_country": {
                    "type": "string",
                    "description": "Code pays ISO 3166-1 alpha-2 optionnel (deux lettres ASCII, par ex. `FR`) qui ajuste la normalisation du nom de l'entreprise pour `expected_company_name`. Utilisé uniquement avec `expected_company_name`."
                  },
                  "document_ai_name_match_score_threshold": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 80,
                    "description": "Valeur minimale de `name_match_score` (0–100) pour considérer le nom comme correspondant. Un score inférieur ajoute `DOCUMENT_AI_NAME_MISMATCH`, régi par `document_ai_name_mismatch_action`.",
                    "example": 80
                  },
                  "document_ai_unreadable_document_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "REVIEW",
                      "NO_ACTION"
                    ],
                    "default": "REVIEW",
                    "description": "Ce qu'il faut faire lorsqu'aucun champ n'a pu être lu à partir du document (`DOCUMENT_AI_UNREADABLE_DOCUMENT`)."
                  },
                  "document_ai_missing_required_fields_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "REVIEW",
                      "NO_ACTION"
                    ],
                    "default": "REVIEW",
                    "description": "Ce qu'il faut faire lorsqu'au moins un champ `required` n'a pas pu être lu (`DOCUMENT_AI_MISSING_REQUIRED_FIELDS` ; `additional_data.missing_fields` les énumère)."
                  },
                  "document_ai_document_tampering_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "REVIEW",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Ce qu'il faut faire lorsque l'analyse médico-légale PDF/EXIF suspecte une manipulation — modification après signature numérique, éditeur PDF connu, manipulation par texte superposé, réexportation suspecte, anomalies d'image (`DOCUMENT_AI_SUSPECTED_MANIPULATION`)."
                  },
                  "document_ai_name_mismatch_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "REVIEW",
                      "NO_ACTION"
                    ],
                    "default": "NO_ACTION",
                    "description": "Ce qu'il faut faire lorsque `name_match_score` est inférieur au seuil (`DOCUMENT_AI_NAME_MISMATCH`)."
                  },
                  "document_ai_unsupported_file_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "REVIEW",
                      "NO_ACTION"
                    ],
                    "default": "REVIEW",
                    "description": "Que faire lorsque le fichier importé est vide ou n'est pas un fichier traitable (`DOCUMENT_AI_UNSUPPORTED_FILE`)."
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Lorsque la valeur est `true` (par défaut), conserve l'appel sous la forme d'une session de type API — visible dans la Business Console, récupérable via `GET /v3/session/{sessionId}/decision/` à l'aide du `request_id` renvoyé, avec le document importé, les valeurs extraites, les définitions de champs et l'instantané de correspondance de nom stockés. Lorsque la valeur est `false`, rien n'est stocké et `request_id` est un UUID éphémère servant uniquement à la corrélation des réponses ; l'appel reste facturé.",
                    "example": true
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Chaîne opaque optionnelle (votre identifiant d'utilisateur interne, e-mail, UUID…) stockée sur la session persistée et renvoyée dans la réponse. Utilisez-la pour corréler les appels d'API avec vos propres enregistrements et pour filtrer les sessions ultérieurement.",
                    "example": "user-123"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Objet JSON optionnel stocké avec la session (lorsque `save_api_request=true`) et renvoyé dans la réponse. Dans les requêtes multipart, envoyez-le sous forme de champ textuel encodé en JSON (par ex. `metadata={\"flow\":\"onboarding\"}`) — il est analysé sous forme d'objet.",
                    "example": {
                      "flow": "onboarding"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document traité. `document_ai.status` est `Approved`, `Declined` ou `In Review` ; chaque problème détecté est détaillé dans `document_ai.warnings`. Un document problématique renvoie tout de même `200` — inspectez le corps de la réponse, pas seulement le code HTTP. Lorsque `save_api_request=true`, `request_id` est l'identifiant de la session enregistrée.",
            "content": {
              "application/json": {
                "examples": {
                  "Approved": {
                    "summary": "Fiche de paie lue sans erreur, nom correspondant",
                    "value": {
                      "request_id": "9d6a3b1e-2f0c-4a8e-9b7d-1c2e3f4a5b6c",
                      "document_ai": {
                        "status": "Approved",
                        "extracted_data": {
                          "employer_name": "Acme Payments Ltd",
                          "employee_name": "Sophia Martinez",
                          "net_pay": 3120.5,
                          "pay_date": "2026-07-31"
                        },
                        "detected_codes": [
                          {
                            "type": "CODE_128",
                            "page_number": 1,
                            "position": [
                              [
                                96,
                                456
                              ],
                              [
                                96,
                                616
                              ],
                              [
                                1012,
                                611
                              ],
                              [
                                1015,
                                456
                              ]
                            ],
                            "x": 96,
                            "y": 456,
                            "width": 919,
                            "height": 160,
                            "page_width": 1200,
                            "page_height": 1700,
                            "raw_payload": "SU5WLTIwMjYtMDA0Mg==",
                            "parsed_payload": "INV-2026-0042"
                          }
                        ],
                        "fields": [
                          {
                            "key": "employer_name",
                            "name": "Employer name",
                            "instruction": "The employer or company issuing the payslip.",
                            "type": "text",
                            "required": true,
                            "is_full_name": false
                          },
                          {
                            "key": "employee_name",
                            "name": "Employee name",
                            "instruction": "The full name of the employee as printed on the payslip.",
                            "type": "text",
                            "required": true,
                            "is_full_name": true
                          },
                          {
                            "key": "net_pay",
                            "name": "Net pay",
                            "instruction": "The net amount paid to the employee for the period.",
                            "type": "number",
                            "required": true,
                            "is_full_name": false
                          },
                          {
                            "key": "pay_date",
                            "name": "Pay date",
                            "instruction": "The payment date shown on the payslip.",
                            "type": "date",
                            "required": false,
                            "is_full_name": false
                          }
                        ],
                        "name_match_score": 100.0,
                        "name_on_document": "Sophia Martinez",
                        "warnings": []
                      },
                      "vendor_data": "user-123",
                      "metadata": {
                        "flow": "onboarding"
                      },
                      "created_at": "2026-08-19T16:40:12.318Z"
                    }
                  },
                  "In Review — missing required field": {
                    "summary": "`net_pay` n'a pas pu être lu ; action par défaut REVIEW",
                    "value": {
                      "request_id": "3f2a9c7b-5d4e-4b1a-8c6f-0e9d8c7b6a5f",
                      "document_ai": {
                        "status": "In Review",
                        "extracted_data": {
                          "employer_name": "Acme Payments Ltd",
                          "employee_name": "Sophia Martinez",
                          "net_pay": null,
                          "pay_date": "2026-07-31"
                        },
                        "detected_codes": [],
                        "fields": [
                          {
                            "key": "employer_name",
                            "name": "Employer name",
                            "instruction": "The employer or company issuing the payslip.",
                            "type": "text",
                            "required": true,
                            "is_full_name": false
                          },
                          {
                            "key": "employee_name",
                            "name": "Employee name",
                            "instruction": "The full name of the employee as printed on the payslip.",
                            "type": "text",
                            "required": true,
                            "is_full_name": true
                          },
                          {
                            "key": "net_pay",
                            "name": "Net pay",
                            "instruction": "The net amount paid to the employee for the period.",
                            "type": "number",
                            "required": true,
                            "is_full_name": false
                          },
                          {
                            "key": "pay_date",
                            "name": "Pay date",
                            "instruction": "The payment date shown on the payslip.",
                            "type": "date",
                            "required": false,
                            "is_full_name": false
                          }
                        ],
                        "name_match_score": 100.0,
                        "name_on_document": "Sophia Martinez",
                        "warnings": [
                          {
                            "risk": "DOCUMENT_AI_MISSING_REQUIRED_FIELDS",
                            "feature": "DOCUMENT_AI",
                            "additional_data": {
                              "missing_fields": [
                                "Net pay"
                              ]
                            },
                            "log_type": "warning",
                            "short_description": "Required fields could not be extracted",
                            "long_description": "One or more fields configured as required could not be extracted from the uploaded document."
                          }
                        ]
                      },
                      "vendor_data": null,
                      "metadata": null,
                      "created_at": "2026-08-19T16:41:05.002Z"
                    }
                  },
                  "Declined — suspected manipulation": {
                    "summary": "L'analyse forensique de PDF a signalé un éditeur connu ; action par défaut DECLINE",
                    "value": {
                      "request_id": "7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
                      "document_ai": {
                        "status": "Declined",
                        "extracted_data": {
                          "employer_name": "Acme Payments Ltd",
                          "employee_name": "Sophia Martinez",
                          "net_pay": 3120.5,
                          "pay_date": "2026-07-31"
                        },
                        "detected_codes": [],
                        "fields": [
                          {
                            "key": "employer_name",
                            "name": "Employer name",
                            "instruction": "The employer or company issuing the payslip.",
                            "type": "text",
                            "required": true,
                            "is_full_name": false
                          },
                          {
                            "key": "employee_name",
                            "name": "Employee name",
                            "instruction": "The full name of the employee as printed on the payslip.",
                            "type": "text",
                            "required": true,
                            "is_full_name": true
                          },
                          {
                            "key": "net_pay",
                            "name": "Net pay",
                            "instruction": "The net amount paid to the employee for the period.",
                            "type": "number",
                            "required": true,
                            "is_full_name": false
                          },
                          {
                            "key": "pay_date",
                            "name": "Pay date",
                            "instruction": "The payment date shown on the payslip.",
                            "type": "date",
                            "required": false,
                            "is_full_name": false
                          }
                        ],
                        "name_match_score": null,
                        "name_on_document": "Sophia Martinez",
                        "warnings": [
                          {
                            "risk": "DOCUMENT_AI_SUSPECTED_MANIPULATION",
                            "feature": "DOCUMENT_AI",
                            "additional_data": {
                              "detection_method": "known_editor",
                              "processed_by_known_editor": "ilovepdf"
                            },
                            "log_type": "error",
                            "short_description": "Suspected document manipulation",
                            "long_description": "The system detected signs of potential manipulation or editing in the uploaded document."
                          }
                        ]
                      },
                      "vendor_data": null,
                      "metadata": null,
                      "created_at": "2026-08-19T16:42:40.771Z"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "document_ai": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "Declined",
                            "In Review"
                          ],
                          "description": "`Approved` lorsqu'aucun avertissement n'aboutit à un refus ou à un examen ; `Declined` lorsqu'au moins un risque correspond à `DECLINE` ; sinon `In Review` lorsqu'au moins un correspond à `REVIEW`. La liste `warnings` en explique la raison."
                        },
                        "extracted_data": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Une entrée par clé de champ demandée. Les valeurs sont typées selon le `type` de champ — chaînes de caractères pour `text`, nombres pour `number`, chaînes `YYYY-MM-DD` pour `date` — ou `null` lorsque la valeur n'a pas pu être lue.",
                          "example": {
                            "employer_name": "Acme Payments Ltd",
                            "employee_name": "Sophia Martinez",
                            "net_pay": 3120.5,
                            "pay_date": "2026-07-31"
                          }
                        },
                        "detected_codes": {
                          "type": "array",
                          "description": "Codes QR et codes-barres détectés sur chaque page traitée. Vide si aucun n'est trouvé. Un code QR localisé mais indécodable a `parsed_payload: null`.",
                          "items": {
                            "$ref": "#/components/schemas/DocumentAIDetectedCode"
                          }
                        },
                        "fields": {
                          "type": "array",
                          "description": "Les définitions de champs normalisées utilisées pour cette extraction, renvoyées en écho (également stockées avec la session lorsque `save_api_request=true`).",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "instruction": {
                                "type": "string"
                              },
                              "type": {
                                "type": "string",
                                "enum": [
                                  "text",
                                  "number",
                                  "date"
                                ]
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "is_full_name": {
                                "type": "boolean"
                              }
                            }
                          }
                        },
                        "name_match_score": {
                          "type": "number",
                          "nullable": true,
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Similarité approximative (0–100) entre `name_on_document` et le nom attendu de la personne/l'entreprise. Renvoyée dès lors qu'une valeur de nom et un nom attendu existent tous deux — aussi bien en cas de correspondance **qu'en cas** de non-correspondance ; `null` sinon.",
                          "example": 96.0
                        },
                        "name_on_document": {
                          "type": "string",
                          "nullable": true,
                          "description": "La valeur de nom extraite du document (le champ `is_full_name`, ou le premier champ de texte de type nom) qui a été comparée au nom attendu. `null` lorsqu'aucune valeur de nom n'était disponible.",
                          "example": "Sophia Martinez"
                        },
                        "warnings": {
                          "type": "array",
                          "description": "Vide en cas d'approbation sans réserve. Chaque entrée explique un risque détecté ; les entrées avec `log_type: \"error\"` définissent `status` sur `Declined`, les entrées avec `log_type: \"warning\"` le définissent sur `In Review`.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "risk": {
                                "type": "string",
                                "enum": [
                                  "DOCUMENT_AI_UNREADABLE_DOCUMENT",
                                  "DOCUMENT_AI_MISSING_REQUIRED_FIELDS",
                                  "DOCUMENT_AI_SUSPECTED_MANIPULATION",
                                  "DOCUMENT_AI_NAME_MISMATCH",
                                  "DOCUMENT_AI_UNSUPPORTED_FILE"
                                ],
                                "description": "Code de risque lisible par machine. Chacun est régi par l'option de requête `document_ai_*_action` correspondante.",
                                "example": "DOCUMENT_AI_MISSING_REQUIRED_FIELDS"
                              },
                              "feature": {
                                "type": "string",
                                "enum": [
                                  "DOCUMENT_AI"
                                ],
                                "description": "Fonctionnalité ayant émis l'avertissement. Toujours `DOCUMENT_AI` sur cet endpoint."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "additionalProperties": true,
                                "description": "Contexte supplémentaire pour le risque : `{\"missing_fields\": [\"Net pay\"]}` pour les champs obligatoires manquants, `{\"name_on_document\", \"score\", \"threshold\"}` pour une discordance de nom, et le résultat d'analyse médico-légale (`detection_method`, détails sur le producteur/l'éditeur) pour une suspicion de manipulation. `null` lorsqu'il n'y a rien à ajouter.",
                                "example": {
                                  "missing_fields": [
                                    "Net pay"
                                  ]
                                }
                              },
                              "log_type": {
                                "type": "string",
                                "enum": [
                                  "error",
                                  "warning",
                                  "information"
                                ],
                                "description": "Gravité dérivée de l'action configurée : `error` (DECLINE), `warning` (REVIEW), `information` (NO_ACTION)."
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Description du risque en une ligne lisible par l'utilisateur.",
                                "example": "Required fields could not be extracted"
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication lisible par l'humain, interpolée avec `additional_data` le cas échéant."
                              }
                            }
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Écho des `vendor_data` que vous avez envoyées, ou `null`."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Écho de l'objet `metadata` que vous avez envoyé, ou `null`."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Moment où la requête a été traitée (UTC, ISO 8601)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation ou de traitement. Les problèmes au niveau des champs renvoient l'enveloppe standard de DRF (un tableau de messages par champ concerné). Les documents chiffrés ou illisibles et les échecs d'extraction renvoient `{\"error\": ...}`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing document": {
                    "summary": "`document` n'est pas inclus dans les données du formulaire",
                    "value": {
                      "document": [
                        "No file was submitted."
                      ]
                    }
                  },
                  "Invalid fields payload": {
                    "summary": "`fields` n'est pas une chaîne contenant un tableau encodé en JSON",
                    "value": {
                      "fields": [
                        "fields must be a valid JSON array string."
                      ]
                    }
                  },
                  "Duplicate field keys": {
                    "summary": "Deux éléments partagent la même `key`",
                    "value": {
                      "fields": [
                        "Every fields item must have a unique key."
                      ]
                    }
                  },
                  "Conflicting expectations": {
                    "summary": "Attentes concernant la personne et l'entreprise envoyées conjointement",
                    "value": {
                      "non_field_errors": [
                        "Provide either person expected-name fields or expected_company_name, not both."
                      ]
                    }
                  },
                  "Invalid metadata": {
                    "summary": "`metadata` n'est pas un objet JSON (ou contient un caractère NUL)",
                    "value": {
                      "metadata": [
                        "Metadata must be a JSON object."
                      ]
                    }
                  },
                  "Oversized vendor_data": {
                    "summary": "`vendor_data` dépasse la limite de 2 000 octets",
                    "value": {
                      "vendor_data": [
                        "vendor_data is too long (maximum 2000 bytes)."
                      ]
                    }
                  },
                  "Encrypted PDF": {
                    "summary": "PDF protégé par mot de passe",
                    "value": {
                      "error": "The PDF is encrypted. Please upload a decrypted PDF or a photo instead."
                    }
                  },
                  "Extraction failed": {
                    "summary": "Le pipeline d'extraction n'a pas pu traiter le document",
                    "value": {
                      "error": [
                        "Error extracting Document AI information"
                      ]
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants (ainsi que les organisations facturées par contrat dont la grille tarifaire ne comporte aucune entrée pour l'API Document AI) renvoient `403` avec `{\"error\": ...}` avant tout traitement de document.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  },
                  "Contract rate missing": {
                    "summary": "Organisation facturée sur contrat dont la grille tarifaire ne comporte aucune entrée pour l'API Document AI",
                    "value": {
                      "error": "Document AI API is not included in your contract rate card. Contact support@didit.me to enable it."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/DocumentProcessingBusy"
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.document_ai.analyze(\n    document=open(\"document.pdf\", \"rb\"),\n    fields=\"[{\\\"key\\\": \\\"employer_name\\\", \\\"name\\\": \\\"Employer name\\\", \\\"instruction\\\": \\\"The employer or company issuing the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"employee_name\\\", \\\"name\\\": \\\"Employee name\\\", \\\"instruction\\\": \\\"The full name of the employee as printed on the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": true}, {\\\"key\\\": \\\"net_pay\\\", \\\"name\\\": \\\"Net pay\\\", \\\"instruction\\\": \\\"The net amount paid to the employee for the period.\\\", \\\"type\\\": \\\"number\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"pay_date\\\", \\\"name\\\": \\\"Pay date\\\", \\\"instruction\\\": \\\"The payment date shown on the payslip.\\\", \\\"type\\\": \\\"date\\\", \\\"required\\\": false, \\\"is_full_name\\\": false}]\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.documentAi.analyze({\n  document: await fileFromPath(\"document.pdf\"),\n  fields: \"[{\\\"key\\\": \\\"employer_name\\\", \\\"name\\\": \\\"Employer name\\\", \\\"instruction\\\": \\\"The employer or company issuing the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"employee_name\\\", \\\"name\\\": \\\"Employee name\\\", \\\"instruction\\\": \\\"The full name of the employee as printed on the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": true}, {\\\"key\\\": \\\"net_pay\\\", \\\"name\\\": \\\"Net pay\\\", \\\"instruction\\\": \\\"The net amount paid to the employee for the period.\\\", \\\"type\\\": \\\"number\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"pay_date\\\", \\\"name\\\": \\\"Pay date\\\", \\\"instruction\\\": \\\"The payment date shown on the payslip.\\\", \\\"type\\\": \\\"date\\\", \\\"required\\\": false, \\\"is_full_name\\\": false}]\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.DocumentAi.Analyze(ctx, didit.DocumentAiAnalyzeParams{\n\tDocument: didit.FileFromPath(\"document.pdf\"),\n\tFields:   \"[{\\\"key\\\": \\\"employer_name\\\", \\\"name\\\": \\\"Employer name\\\", \\\"instruction\\\": \\\"The employer or company issuing the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"employee_name\\\", \\\"name\\\": \\\"Employee name\\\", \\\"instruction\\\": \\\"The full name of the employee as printed on the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": true}, {\\\"key\\\": \\\"net_pay\\\", \\\"name\\\": \\\"Net pay\\\", \\\"instruction\\\": \\\"The net amount paid to the employee for the period.\\\", \\\"type\\\": \\\"number\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"pay_date\\\", \\\"name\\\": \\\"Pay date\\\", \\\"instruction\\\": \\\"The payment date shown on the payslip.\\\", \\\"type\\\": \\\"date\\\", \\\"required\\\": false, \\\"is_full_name\\\": false}]\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\nimport me.didit.types.DocumentAiAnalyzeParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.documentAi().analyze(DocumentAiAnalyzeParams.builder()\n        .document(Path.of(\"document.pdf\"))\n        .fields(\"[{\\\"key\\\": \\\"employer_name\\\", \\\"name\\\": \\\"Employer name\\\", \\\"instruction\\\": \\\"The employer or company issuing the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"employee_name\\\", \\\"name\\\": \\\"Employee name\\\", \\\"instruction\\\": \\\"The full name of the employee as printed on the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": true}, {\\\"key\\\": \\\"net_pay\\\", \\\"name\\\": \\\"Net pay\\\", \\\"instruction\\\": \\\"The net amount paid to the employee for the period.\\\", \\\"type\\\": \\\"number\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"pay_date\\\", \\\"name\\\": \\\"Pay date\\\", \\\"instruction\\\": \\\"The payment date shown on the payslip.\\\", \\\"type\\\": \\\"date\\\", \\\"required\\\": false, \\\"is_full_name\\\": false}]\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->documentAi->analyze([\n    'document' => File::fromPath('document.pdf'),\n    'fields' => '[{\"key\": \"employer_name\", \"name\": \"Employer name\", \"instruction\": \"The employer or company issuing the payslip.\", \"type\": \"text\", \"required\": true, \"is_full_name\": false}, {\"key\": \"employee_name\", \"name\": \"Employee name\", \"instruction\": \"The full name of the employee as printed on the payslip.\", \"type\": \"text\", \"required\": true, \"is_full_name\": true}, {\"key\": \"net_pay\", \"name\": \"Net pay\", \"instruction\": \"The net amount paid to the employee for the period.\", \"type\": \"number\", \"required\": true, \"is_full_name\": false}, {\"key\": \"pay_date\", \"name\": \"Pay date\", \"instruction\": \"The payment date shown on the payslip.\", \"type\": \"date\", \"required\": false, \"is_full_name\": false}]',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.document_ai.analyze(\n  document: Pathname(\"document.pdf\"),\n  fields: \"[{\\\"key\\\": \\\"employer_name\\\", \\\"name\\\": \\\"Employer name\\\", \\\"instruction\\\": \\\"The employer or company issuing the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"employee_name\\\", \\\"name\\\": \\\"Employee name\\\", \\\"instruction\\\": \\\"The full name of the employee as printed on the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": true}, {\\\"key\\\": \\\"net_pay\\\", \\\"name\\\": \\\"Net pay\\\", \\\"instruction\\\": \\\"The net amount paid to the employee for the period.\\\", \\\"type\\\": \\\"number\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"pay_date\\\", \\\"name\\\": \\\"Pay date\\\", \\\"instruction\\\": \\\"The payment date shown on the payslip.\\\", \\\"type\\\": \\\"date\\\", \\\"required\\\": false, \\\"is_full_name\\\": false}]\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.DocumentAi.AnalyzeAsync(new DocumentAiAnalyzeParams\n{\n    Document = FileUpload.FromPath(\"document.pdf\"),\n    Fields = \"[{\\\"key\\\": \\\"employer_name\\\", \\\"name\\\": \\\"Employer name\\\", \\\"instruction\\\": \\\"The employer or company issuing the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"employee_name\\\", \\\"name\\\": \\\"Employee name\\\", \\\"instruction\\\": \\\"The full name of the employee as printed on the payslip.\\\", \\\"type\\\": \\\"text\\\", \\\"required\\\": true, \\\"is_full_name\\\": true}, {\\\"key\\\": \\\"net_pay\\\", \\\"name\\\": \\\"Net pay\\\", \\\"instruction\\\": \\\"The net amount paid to the employee for the period.\\\", \\\"type\\\": \\\"number\\\", \\\"required\\\": true, \\\"is_full_name\\\": false}, {\\\"key\\\": \\\"pay_date\\\", \\\"name\\\": \\\"Pay date\\\", \\\"instruction\\\": \\\"The payment date shown on the payslip.\\\", \\\"type\\\": \\\"date\\\", \\\"required\\\": false, \\\"is_full_name\\\": false}]\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/aml/": {
      "post": {
        "summary": "Filtrage AML (autonome)",
        "operationId": "post_v3aml",
        "x-didit-sdk": {
          "resource": "aml",
          "method": "screen",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Clé de sécurité de nouvelle tentative optionnelle, jusqu'à 255 caractères. La réutilisation de la même clé avec le même corps de requête renvoie la réponse d'origine sans exécuter ni facturer un second filtrage. La réutilisation de la clé avec un corps différent renvoie `409`.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "description": "Effectuez le filtrage d'une personne ou d'une entreprise par rapport aux jeux de données PEP, de sanctions, d'avertissements/listes de surveillance et de presse négative en un seul appel.\n\n**Modèle à deux scores.** Chaque résultat comporte un `match_score` (0–100, confiance dans l'identité) et un `risk_score` (0–100, risque lié à l'entité). Les résultats dont le `match_score` est inférieur à `aml_match_score_threshold` (par défaut **93**) sont marqués `review_status: \"False Positive\"` et ignorés pour l'évaluation du risque ; le `risk_score` le plus élevé parmi les résultats restants devient `aml.score`. Le `aml.status` final suit vos seuils : `score` > `aml_score_review_threshold` (par défaut **100**) → `Declined` ; `score` > `aml_score_approve_threshold` (par défaut **80**) → `In Review` ; sinon `Approved`. Dès lors que `score` est non nul et ≥ au seuil d'approbation, un avertissement `POSSIBLE_MATCH_FOUND` est ajouté (un score exactement égal à 0 ne génère jamais d'avertissement).\n\n**Pondérations du score de correspondance.** `aml_name_weight` + `aml_dob_weight` + `aml_country_weight` doivent totaliser exactement 100 (par défaut 60/25/15). Les composantes absentes de la requête sont écartées par renormalisation ; un `document_number` correspondant fait office de clé universelle qui remplace `match_score` par 100.\n\n**Latence.** Les filtrages simples s'exécutent généralement en quelques secondes. Avec `include_adverse_media=true`, l'API attend l'enrichissement par la presse négative (une pause initiale d'environ 5 s plus jusqu'à environ 25 s d'interrogation) — configurez un délai d'attente client d'**au moins 60 secondes**.\n\n**Persistance.** `save_api_request` est défini par défaut sur **true** : le filtrage est conservé sous forme de session (`request_id` fonctionne avec `GET /v3/session/{sessionId}/decision/`), il apparaît dans la console, un webhook `status.updated` est déclenché, et les statuts d'examen des résultats peuvent être mis à jour ultérieurement. Avec `save_api_request=false`, rien n'est stocké et `request_id` est un identifiant de corrélation temporaire. `include_ongoing_monitoring=true` continue d'analyser à nouveau le profil et nécessite `save_api_request=true` (imposé par un code `400`).\n\n**Idempotence.** Envoyez un en-tête `Idempotency-Key` lors d'une nouvelle tentative après un dépassement de délai ou une erreur temporaire. La clé est circonscrite à votre application et au corps exact de la requête. La première requête terminée stocke sa réponse ; les nouvelles tentatives identiques ultérieures renvoient cette même réponse et n'exécutent ni ne facturent un autre filtrage AML. Si la requête d'origine est toujours en cours d'exécution, réessayez plus tard avec la même clé. Si la même clé est réutilisée avec un corps différent, l'API renvoie `409`.\n\n**Facturation.** Un crédit d'API AML est débité après le premier filtrage réussi. Les réponses réémises de manière idempotente ne sont pas facturées à nouveau ; un solde insuffisant renvoie `403` avant tout nouveau filtrage.\n\n**Sandbox.** Les clés des applications sandbox ignorent entièrement le filtrage et la facturation et renvoient un résultat simulé — `Approved` sans aucun résultat, sauf si vous transmettez `sandbox_scenario`. `save_api_request` fonctionne de la même manière qu'avec les clés de production, de sorte qu'un filtrage sandbox enregistré peut être récupéré via `GET /v3/session/{sessionId}/decision/` et `GET /v3/session/{sessionId}/generate-pdf/`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "full_name"
                ],
                "properties": {
                  "full_name": {
                    "type": "string",
                    "minLength": 2,
                    "description": "Nom complet de la personne ou de l'entreprise à filtrer. Minimum **2 caractères** - seuil plancher propre au fournisseur de filtrage. Un nom plus court ou vide renvoie `400` sur ce champ avant tout filtrage, de sorte que rien n'est facturé.",
                    "example": "Antonio Ejemplo Modelo"
                  },
                  "entity_type": {
                    "type": "string",
                    "enum": [
                      "person",
                      "company"
                    ],
                    "default": "person",
                    "description": "Type d'entité à filtrer. Valeur par défaut : `person`."
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "description": "Date de naissance (personnes) ou date de constitution (entreprises), `YYYY-MM-DD`. Améliore la précision de la correspondance via le poids de la date de naissance.",
                    "example": "1972-02-29"
                  },
                  "nationality": {
                    "type": "string",
                    "description": "Code pays ISO 3166-1 **alpha-2** (par exemple `ES`). Les codes invalides renvoient `400`. Améliore la précision de correspondance grâce au poids attribué au pays.",
                    "example": "ES"
                  },
                  "document_number": {
                    "type": "string",
                    "description": "Numéro du document d'identité. Non pondéré — agit comme une clé déterminante : une correspondance exacte remplace le `match_score` du résultat par 100, une discordance stricte le pénalise. Envoyé au fournisseur de filtrage comme filtre de recherche uniquement lorsqu'il comporte **2-50 caractères** ; une valeur en dehors de cette plage est acceptée et stockée, et le filtrage s'exécute et est facturé normalement, mais n'est simplement pas affiné par le numéro de document."
                  },
                  "aml_score_approve_threshold": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 80,
                    "description": "Seuil de score de risque auquel ou en dessous duquel le résultat est `Approved`. Doit être ≤ `aml_score_review_threshold` (sinon `400`)."
                  },
                  "aml_score_review_threshold": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 100,
                    "description": "Seuil de score de risque au-dessus duquel le résultat est `Declined`. Les scores situés entre les deux seuils produisent `In Review`."
                  },
                  "aml_name_weight": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 60,
                    "description": "Poids de la similarité de nom dans le score de correspondance par correspondance. La somme des trois poids doit être exactement égale à 100 (sinon `400`)."
                  },
                  "aml_dob_weight": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 25,
                    "description": "Poids de la date de naissance dans le score de correspondance par correspondance."
                  },
                  "aml_country_weight": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 15,
                    "description": "Poids du pays/de la nationalité dans le score de correspondance par correspondance."
                  },
                  "aml_match_score_threshold": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 93,
                    "description": "Seuil par résultat : les résultats avec un `match_score` inférieur à cette valeur sont `False Positive` (exclus de l'évaluation du risque) ; ceux atteignant ou dépassant cette valeur sont des correspondances possibles `Unreviewed`."
                  },
                  "include_adverse_media": {
                    "type": "boolean",
                    "default": false,
                    "description": "Rechercher également la presse négative dans les médias d'information. Ajoute jusqu'à ~30 s de latence pendant la collecte des résultats — utilisez un délai d'expiration client ≥ 60 s."
                  },
                  "include_ongoing_monitoring": {
                    "type": "boolean",
                    "default": false,
                    "description": "Continuer à filtrer ce profil et transmettre les modifications par webhook. Nécessite `save_api_request=true` (sinon `400`)."
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Conserver le filtrage en tant que session (visibilité dans la console, endpoint de décision, webhooks, examen des correspondances). Définissez sur `false` pour une vérification sans état."
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Votre identifiant pour l'utilisateur filtré ; renvoyé en écho et conservé avec la session."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "JSON libre stocké avec la requête et renvoyé en écho."
                  },
                  "sandbox_scenario": {
                    "type": "string",
                    "description": "Identifiant de scénario réservé à la sandbox. Accepté uniquement lorsque la clé API appartient à une application en mode sandbox ; rejeté sur les applications en production. Un filtrage autonome n'ayant pas de session à armer, le slug est directement transmis dans la requête de filtrage : `decline_aml_hit` renvoie une correspondance conforme au format de production et clôture le filtrage avec le statut `Declined`, `review_aml_possible_match` le clôture avec le statut `In Review`, et un scénario n'armant aucun résultat AML laisse le filtrage vierge. Consultez le catalogue des scénarios à GET /v1/sandbox/scenarios/ ou [Sandbox et données de test](/fr/integration/sandbox-testing).",
                    "example": "decline_aml_hit"
                  }
                }
              },
              "example": {
                "full_name": "Antonio Ejemplo Modelo",
                "entity_type": "person",
                "date_of_birth": "1972-02-29",
                "nationality": "ES",
                "include_adverse_media": false,
                "vendor_data": "user-1234"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/aml/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -H 'Idempotency-Key: aml-user-1234-2026-08-20' \\\n  -d '{\n    \"full_name\": \"Antonio Ejemplo Modelo\",\n    \"entity_type\": \"person\",\n    \"date_of_birth\": \"1972-02-29\",\n    \"nationality\": \"ES\",\n    \"include_adverse_media\": false,\n    \"vendor_data\": \"user-1234\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.aml.screen(\n    full_name=\"Antonio Ejemplo Modelo\",\n    entity_type=\"person\",\n    date_of_birth=\"1972-02-29\",\n    nationality=\"ES\",\n    include_adverse_media=False,\n    vendor_data=\"user-1234\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.aml.screen({\n  full_name: \"Antonio Ejemplo Modelo\",\n  entity_type: \"person\",\n  date_of_birth: \"1972-02-29\",\n  nationality: \"ES\",\n  include_adverse_media: false,\n  vendor_data: \"user-1234\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.AML.Screen(ctx, didit.AMLScreenParams{\n\tFullName:            \"Antonio Ejemplo Modelo\",\n\tEntityType:          didit.Some(didit.AMLScreenParamsEntityType(\"person\")),\n\tDateOfBirth:         didit.String(\"1972-02-29\"),\n\tNationality:         didit.String(\"ES\"),\n\tIncludeAdverseMedia: didit.Bool(false),\n\tVendorData:          didit.String(\"user-1234\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.LocalDate;\nimport me.didit.Didit;\nimport me.didit.types.AmlScreenParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.aml().screen(AmlScreenParams.builder()\n        .fullName(\"Antonio Ejemplo Modelo\")\n        .entityType(AmlScreenParams.EntityType.of(\"person\"))\n        .dateOfBirth(LocalDate.parse(\"1972-02-29\"))\n        .nationality(\"ES\")\n        .includeAdverseMedia(false)\n        .vendorData(\"user-1234\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->aml->screen([\n    'full_name' => 'Antonio Ejemplo Modelo',\n    'entity_type' => 'person',\n    'date_of_birth' => '1972-02-29',\n    'nationality' => 'ES',\n    'include_adverse_media' => false,\n    'vendor_data' => 'user-1234',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.aml.screen(\n  full_name: \"Antonio Ejemplo Modelo\",\n  entity_type: \"person\",\n  date_of_birth: \"1972-02-29\",\n  nationality: \"ES\",\n  include_adverse_media: false,\n  vendor_data: \"user-1234\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Aml.ScreenAsync(new AmlScreenParams\n{\n    FullName = \"Antonio Ejemplo Modelo\",\n    EntityType = new AmlScreenParamsEntityType(\"person\"),\n    DateOfBirth = \"1972-02-29\",\n    Nationality = \"ES\",\n    IncludeAdverseMedia = false,\n    VendorData = \"user-1234\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Filtrage terminé. `aml.status` reflète vos seuils ; chaque résultat atteignant ou dépassant le seuil minimal interne d'inclusion est listé dans `aml.hits` avec son `match_score` d'identité, son `risk_score` d'entité et une décomposition `score_breakdown` expliquant la correspondance.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "aml": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "In Review",
                            "Declined"
                          ],
                          "description": "`Declined` lorsque `score` > `aml_score_review_threshold` ; `In Review` lorsque `score` > `aml_score_approve_threshold` ; `Approved` dans les autres cas (y compris lorsqu'aucun score n'est disponible)."
                        },
                        "total_hits": {
                          "type": "integer",
                          "description": "Nombre d'entrées dans `hits`."
                        },
                        "entity_type": {
                          "type": "string",
                          "enum": [
                            "person",
                            "company"
                          ],
                          "description": "Type d'entité filtré renvoyé."
                        },
                        "hits": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "description": "Un résultat de filtrage. `match_score` (0–100) mesure la confiance dans l'identité — les correspondances inférieures à `aml_match_score_threshold` sont marquées avec `review_status: \"False Positive\"` et exclues de l'évaluation du risque ; les correspondances supérieures ou égales à ce seuil sont des correspondances possibles `\"Unreviewed\"`. `risk_score` (0–100) mesure le niveau de risque de l'entité correspondante et détermine le `aml.score` de premier niveau.",
                            "properties": {
                              "id": {
                                "type": "string",
                                "nullable": true,
                                "description": "Identifiant stable de Didit pour le résultat positif : `hit_` suivi de 24 caractères hexadécimaux. La même entité correspondante conserve le même `id` lorsque le sujet fait l'objet d'un nouveau filtrage. Transmettez-le en tant que `hit_id` aux endpoints d'examen des résultats AML."
                              },
                              "url": {
                                "type": "string",
                                "nullable": true,
                                "description": "URL source de l'entité correspondante, lorsqu'elle est disponible."
                              },
                              "match": {
                                "type": "boolean",
                                "nullable": true,
                                "description": "Indicateur de correspondance exacte obsolète. Privilégiez `match_score` + `review_status`."
                              },
                              "score": {
                                "type": "number",
                                "nullable": true,
                                "description": "OBSOLÈTE : score de correspondance pondéré dans la plage 0–1. Utilisez `match_score` à la place."
                              },
                              "match_score": {
                                "type": "number",
                                "nullable": true,
                                "description": "Score de confiance de l'identité (0–100). Comparé à `aml_match_score_threshold` pour séparer les faux positifs des correspondances possibles."
                              },
                              "risk_score": {
                                "type": "number",
                                "nullable": true,
                                "description": "Score de risque de l'entité (0–100). Le `risk_score` le plus élevé parmi les correspondances qui ne sont pas des faux positifs devient le `aml.score` de premier niveau."
                              },
                              "target": {
                                "type": "boolean",
                                "nullable": true
                              },
                              "caption": {
                                "type": "string",
                                "nullable": true,
                                "description": "Nom d'affichage de l'entité correspondante."
                              },
                              "datasets": {
                                "type": "array",
                                "nullable": true,
                                "items": {
                                  "type": "string",
                                  "enum": [
                                    "PEP",
                                    "PEP Level 1",
                                    "PEP Level 2",
                                    "PEP Level 3",
                                    "PEP Level 4",
                                    "Sanctions",
                                    "Adverse Media",
                                    "Warnings and Regulatory Enforcement",
                                    "Fitness and Probity",
                                    "SIP",
                                    "SIE",
                                    "Insolvency",
                                    "Other Lists"
                                  ]
                                },
                                "description": "Catégories de risque dans lesquelles l'entité est répertoriée : `PEP` (avec son niveau, `PEP Level 1` à `PEP Level 4`), `Sanctions`, `Adverse Media`, `Warnings and Regulatory Enforcement`, `Fitness and Probity`, `SIP`, `SIE` ou `Insolvency`. `Other Lists` lorsque la source de l'entité n'indique aucune de ces catégories."
                              },
                              "features": {
                                "type": "object",
                                "nullable": true
                              },
                              "properties": {
                                "type": "object",
                                "nullable": true,
                                "description": "Profil de l'entité : `name`, `alias`, `notes`, `gender`, `birthDate`, `birthPlace`, `nationality`, `position`, ainsi que d'autres tableaux biographiques (chacun pouvant être nul)."
                              },
                              "rca_name": {
                                "type": "string",
                                "nullable": true,
                                "description": "Nom du proche associé concerné grâce auquel l'entité a été mise en correspondance, lorsque le résultat est un RCA."
                              },
                              "pep_matches": {
                                "type": "array",
                                "description": "Entrées de la liste PEP associées à ce résultat.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "list_name": {
                                      "type": "string"
                                    },
                                    "publisher": {
                                      "type": "string"
                                    },
                                    "source_url": {
                                      "type": "string"
                                    },
                                    "description": {
                                      "type": "string"
                                    },
                                    "matched_name": {
                                      "type": "string"
                                    },
                                    "pep_position": {
                                      "type": "string"
                                    },
                                    "date_of_birth": {
                                      "type": "string"
                                    },
                                    "place_of_birth": {
                                      "type": "string"
                                    },
                                    "aliases": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "education": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "other_sources": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  }
                                }
                              },
                              "sanction_matches": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                },
                                "description": "Entrées de listes de sanctions associées à cette correspondance (même format de liste sous-jacente que `pep_matches`, avec des champs spécifiques aux sanctions en plus)."
                              },
                              "warning_matches": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                },
                                "description": "Entrées d'avertissement/de liste de surveillance à l'origine de cette correspondance."
                              },
                              "adverse_media_matches": {
                                "type": "array",
                                "description": "Articles de presse négative. Renseigné uniquement lorsque `include_adverse_media=true`.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "headline": {
                                      "type": "string"
                                    },
                                    "summary": {
                                      "type": "string"
                                    },
                                    "sentiment": {
                                      "type": "string"
                                    },
                                    "sentiment_score": {
                                      "type": "number"
                                    },
                                    "source_url": {
                                      "type": "string"
                                    },
                                    "thumbnail": {
                                      "type": "string",
                                      "nullable": true
                                    },
                                    "country": {
                                      "type": "string",
                                      "nullable": true
                                    },
                                    "author_name": {
                                      "type": "string",
                                      "nullable": true
                                    },
                                    "publication_date": {
                                      "type": "string",
                                      "nullable": true
                                    },
                                    "adverse_keywords": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "other_sources": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  }
                                }
                              },
                              "adverse_media_details": {
                                "type": "object",
                                "nullable": true,
                                "description": "Sentiment agrégé de presse négative pour l'entité (`sentiment`, `sentiment_score`, carte de fréquence `adverse_keywords`). Renseigné uniquement lorsque `include_adverse_media=true`."
                              },
                              "first_seen": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true,
                                "description": "Date et heure de première apparition de l'entité dans les jeux de données."
                              },
                              "last_seen": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true,
                                "description": "Actualisation la plus récente du jeu de données ayant inclus l'entité."
                              },
                              "linked_entities": {
                                "type": "array",
                                "description": "Relations connues de l'entité correspondante (famille, associés, entreprises).",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "name": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "relation": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "status": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "details": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "active": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  }
                                }
                              },
                              "risk_view": {
                                "type": "object",
                                "nullable": true,
                                "description": "Décomposition du risque par dimension (`crimes`, `countries`, `categories`, `custom_list`), chacune avec `score`, `weightage`, `risk_level` et un mappage `risk_scores`."
                              },
                              "additional_information": {
                                "type": "object",
                                "nullable": true,
                                "description": "Contexte supplémentaire au format libre, par exemple un tableau `flag_summary` expliquant pourquoi l'entité est signalée."
                              },
                              "review_status": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "False Positive",
                                  "Unreviewed",
                                  "Confirmed Match",
                                  "Inconclusive"
                                ],
                                "description": "`False Positive` — `match_score` inférieur à `aml_match_score_threshold`, exclu de l'évaluation du risque. `Unreviewed` — correspondance possible en attente d'examen. `Confirmed Match` / `Inconclusive` — définis manuellement par un réviseur (via la Business Console) sur les sessions enregistrées ; cette fonctionnalité d'examen ne fait pas partie de cette spécification."
                              },
                              "score_breakdown": {
                                "type": "object",
                                "nullable": true,
                                "description": "Mode de calcul du `match_score`. Le nom, la date de naissance et le pays apportent chacun `<component>_score` × `<component>_weight_normalized` points ; les poids sont renormalisés lorsqu'un composant est manquant dans les données filtrées. Le numéro de document n'est pas pondéré — il agit comme une « clé maîtresse » : `MATCH` remplace le score par 100, `NEUTRAL` le laisse inchangé, `HARD_MISMATCH` applique une pénalité.",
                                "properties": {
                                  "name_score": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "Similarité brute des noms (0–100)."
                                  },
                                  "name_weight": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "Poids configuré pour le nom (`aml_name_weight`)."
                                  },
                                  "name_weight_normalized": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Poids du nom après renormalisation (0–100)."
                                  },
                                  "name_contribution": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Points que le nom a apportés à `total_score`."
                                  },
                                  "dob_score": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "Score de la date de naissance en pourcentage de son poids (−100 à 100)."
                                  },
                                  "dob_weight": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "Poids configuré pour la date de naissance (`aml_dob_weight`)."
                                  },
                                  "dob_weight_normalized": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Pondération de la date de naissance après renormalisation (0–100)."
                                  },
                                  "dob_contribution": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Points que la date de naissance a apportés à `total_score`."
                                  },
                                  "country_score": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "Score du pays exprimé en pourcentage de son poids (−100 à 100)."
                                  },
                                  "country_weight": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "Poids configuré pour le pays (`aml_country_weight`)."
                                  },
                                  "country_weight_normalized": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Poids du pays après renormalisation (0–100)."
                                  },
                                  "country_contribution": {
                                    "type": "number",
                                    "nullable": true,
                                    "description": "Points que le pays a apportés à `total_score`."
                                  },
                                  "document_number_match_type": {
                                    "type": "string",
                                    "nullable": true,
                                    "enum": [
                                      "MATCH",
                                      "NEUTRAL",
                                      "HARD_MISMATCH"
                                    ],
                                    "description": "Résultat de référence absolue (golden-key) pour la comparaison du numéro de document."
                                  },
                                  "document_number_effect": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "Description lisible par l'humain de l'effet du numéro de document."
                                  },
                                  "total_score": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "Score de correspondance pondéré final (0–100) — reflète `match_score`."
                                  }
                                }
                              }
                            }
                          }
                        },
                        "score": {
                          "type": "number",
                          "nullable": true,
                          "description": "Score de risque AML global (0–100) : le `risk_score` le plus élevé parmi les correspondances qui ne sont pas des faux positifs. Détermine le `status` via les deux seuils."
                        },
                        "screened_data": {
                          "type": "object",
                          "description": "Éléments filtrés renvoyés : `full_name`, `date_of_birth`, `nationality`, `document_number` (les champs absents sont `null`).",
                          "properties": {
                            "full_name": {
                              "type": "string"
                            },
                            "date_of_birth": {
                              "type": "string",
                              "nullable": true
                            },
                            "nationality": {
                              "type": "string",
                              "nullable": true
                            },
                            "document_number": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "feature": {
                                "type": "string",
                                "description": "Fonctionnalité ayant émis l'avertissement."
                              },
                              "risk": {
                                "type": "string",
                                "description": "Identifiant de risque lisible par machine."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "description": "Contexte supplémentaire pour l'avertissement, lorsqu'il est disponible."
                              },
                              "log_type": {
                                "type": "string",
                                "description": "`warning`, `information` ou `error` — manière dont le risque a affecté le résultat."
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Résumé lisible par un humain sur une ligne."
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication complète lisible par un humain."
                              }
                            }
                          },
                          "description": "Contient un avertissement `POSSIBLE_MATCH_FOUND` chaque fois que le `score` est non nul et ≥ `aml_score_approve_threshold` (un score exactement égal à 0 n'émet jamais d'avertissement) ; vide sinon."
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Valeur renvoyée de `vendor_data` que vous avez envoyé."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "description": "Écho des `metadata` que vous avez envoyées."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "No hits (Approved)": {
                    "summary": "Filtrage sans correspondance — zéro résultat",
                    "value": {
                      "request_id": "d27c5509-7a66-45a9-b05e-d69d9f4c336a",
                      "aml": {
                        "status": "Approved",
                        "total_hits": 0,
                        "entity_type": "person",
                        "hits": [],
                        "score": 0,
                        "screened_data": {
                          "full_name": "Maximilian Mustermann-Doe",
                          "date_of_birth": "1992-03-14",
                          "nationality": "DE",
                          "document_number": null
                        },
                        "warnings": []
                      },
                      "vendor_data": "user-1234",
                      "metadata": {
                        "internal_ref": "abc-123"
                      },
                      "created_at": "2026-06-11T10:21:07.013938+00:00"
                    }
                  },
                  "PEP hit (Approved — risk below approve threshold)": {
                    "summary": "Une correspondance possible avec une PEP ; le score de risque de 73 reste inférieur au seuil d'approbation par défaut fixé à 80",
                    "value": {
                      "request_id": "0b7e7a3e-65a1-4f3d-9c7a-1de2f9a40111",
                      "aml": {
                        "status": "Approved",
                        "total_hits": 1,
                        "entity_type": "person",
                        "hits": [
                          {
                            "id": "hit_7c1e9a40b2d35f86e0a4c912",
                            "url": "https://news.example.org/articles/sample",
                            "match": false,
                            "score": 0.93,
                            "match_score": 93.0,
                            "risk_score": 73.0,
                            "target": null,
                            "caption": "Antonio Ejemplo Modelo",
                            "datasets": [
                              "PEP Level 1",
                              "PEP"
                            ],
                            "features": null,
                            "rca_name": "",
                            "first_seen": "2026-01-07T00:00:00",
                            "last_seen": "2026-01-07T00:00:00",
                            "review_status": "Unreviewed",
                            "properties": {
                              "name": [
                                "Antonio Ejemplo Modelo",
                                "Antonio Ejemplo"
                              ],
                              "alias": [
                                "Antonio Ejemplo Modelo",
                                "Ejemplo Modelo, Pedro"
                              ],
                              "notes": [
                                "Prime Minister of Spain"
                              ],
                              "gender": [
                                "male"
                              ],
                              "birthDate": [
                                "1972-02-29"
                              ],
                              "birthPlace": [
                                "Madrid, Spain"
                              ],
                              "nationality": null,
                              "position": null
                            },
                            "risk_view": {
                              "crimes": {
                                "score": 0.0,
                                "weightage": 20,
                                "risk_level": "Low",
                                "risk_scores": {}
                              },
                              "countries": {
                                "score": 9.64,
                                "weightage": 30,
                                "risk_level": "Low",
                                "risk_scores": {
                                  "Spain": 25.71
                                }
                              },
                              "categories": {
                                "score": 62.5,
                                "weightage": 50,
                                "risk_level": "High",
                                "risk_scores": {
                                  "PEP": 100.0,
                                  "PEP Level 1": 100.0
                                }
                              },
                              "custom_list": {}
                            },
                            "score_breakdown": {
                              "name_score": 89,
                              "name_weight": 60,
                              "name_weight_normalized": 60.0,
                              "name_contribution": 53.4,
                              "dob_score": 100,
                              "dob_weight": 25,
                              "dob_weight_normalized": 25.0,
                              "dob_contribution": 25.0,
                              "country_score": 100,
                              "country_weight": 15,
                              "country_weight_normalized": 15.0,
                              "country_contribution": 15.0,
                              "document_number_match_type": "NEUTRAL",
                              "document_number_effect": "No document number provided for screening",
                              "total_score": 93
                            },
                            "pep_matches": [
                              {
                                "aliases": [],
                                "education": [],
                                "list_name": "Presidency of the Government of Spain",
                                "publisher": "Presidency of the Government of Spain",
                                "source_url": "https://news.example.org/articles/sample",
                                "description": "The Presidency of the Government is the central institutional body in Spain that supports the Prime Minister and coordinates the general action of the central government.",
                                "matched_name": "Antonio Ejemplo Modelo",
                                "pep_position": "",
                                "date_of_birth": "1972-02-29",
                                "other_sources": [],
                                "place_of_birth": "Madrid, Spain"
                              }
                            ],
                            "sanction_matches": [],
                            "warning_matches": [],
                            "adverse_media_matches": [],
                            "adverse_media_details": null,
                            "linked_entities": [
                              {
                                "name": [
                                  "Maria Begona Gomez Fernandez"
                                ],
                                "active": [],
                                "status": [],
                                "details": [],
                                "relation": [
                                  "spouse"
                                ]
                              }
                            ],
                            "additional_information": {
                              "flag_summary": [
                                "Antonio Ejemplo Modelo has been flagged as a Level 1 Politically Exposed Person (PEP) from Spain, serving as the President of the Government of Spain."
                              ]
                            }
                          }
                        ],
                        "score": 73.0,
                        "screened_data": {
                          "full_name": "Pedro Sanchez Perez-Castejon",
                          "date_of_birth": "1972-02-29",
                          "nationality": "ES",
                          "document_number": null
                        },
                        "warnings": []
                      },
                      "vendor_data": null,
                      "metadata": null,
                      "created_at": "2026-06-11T10:23:44.812000+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les problèmes au niveau des champs renvoient l'enveloppe standard de DRF (un tableau de messages par champ en cause) ; les règles inter-champs (somme des pondérations, ordre des seuils, surveillance sans enregistrement) renvoient `{\"error\": [...]}`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing full_name": {
                    "summary": "`full_name` est le seul champ obligatoire",
                    "value": {
                      "full_name": [
                        "This field is required."
                      ]
                    }
                  },
                  "Short full_name": {
                    "summary": "`full_name` doit comporter au moins 2 caractères",
                    "value": {
                      "full_name": [
                        "Ensure this field has at least 2 characters."
                      ]
                    }
                  },
                  "Invalid nationality": {
                    "summary": "`nationality` doit être au format ISO 3166-1 alpha-2",
                    "value": {
                      "nationality": [
                        "Invalid ISO 3166-1 alpha-2 country code."
                      ]
                    }
                  },
                  "Weights do not sum to 100": {
                    "summary": "`aml_name_weight` + `aml_dob_weight` + `aml_country_weight` ≠ 100",
                    "value": {
                      "error": [
                        "AML weights must sum to 100. Current sum: 90 (name: 50, dob: 25, country: 15)"
                      ]
                    }
                  },
                  "Thresholds out of order": {
                    "summary": "Seuil d'approbation supérieur au seuil d'examen",
                    "value": {
                      "error": [
                        "Approve threshold (90.0) cannot be greater than review threshold (80.0)"
                      ]
                    }
                  },
                  "Monitoring without saving": {
                    "summary": "`include_ongoing_monitoring=true` avec `save_api_request=false`",
                    "value": {
                      "error": [
                        "Ongoing monitoring can only be enabled when the API request is saved."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout filtrage ou appel à un fournisseur.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/face-search/": {
      "post": {
        "summary": "Recherche faciale",
        "description": "Recherchez une image de visage (1:N) dans l'index de recherche faciale de votre application — visages enregistrés à partir de sessions de vérification, d'appels d'API autonomes enregistrés, de téléversements directs de visages de profils utilisateurs et de vos listes de blocage/d'autorisation — et obtenez des correspondances de similarité classées ainsi que des avertissements de liste de blocage et de doublons.\n\n**Fonctionnement.** Le plus grand visage détecté dans `user_image` est converti en embedding et recherché dans l'index, circonscrit à votre application. Jusqu'à **5 correspondances** au-dessus du seuil minimal de similarité sont renvoyées dans `matches`, chacune avec `similarity_percentage`, la session d'origine (`session_id`, `session_number`, `status`, `vendor_data`), les `user_details` extraits lors de la vérification de document de cette session, les indicateurs `is_blocklisted` / `is_allowlisted`, et un discriminateur `source` (`session`, `imported` ou `list_entry`).\n\n- `search_type=most_similar` (par défaut) classe chaque visage enregistré par similarité — utilisez-le pour la déduplication et l'enquête sur les réseaux de fraude.\n- `search_type=blocklisted_or_approved` restreint les candidats aux visages sur liste de blocage, sur liste d'autorisation, aux visages issus de sessions approuvées et aux visages de profils utilisateurs importés, en classant les entrées sur liste de blocage en premier — utilisez-le lorsque l'objectif principal est le filtrage sur liste de blocage.\n\n`status` est `Declined` uniquement lorsqu'un avertissement `FACE_IN_BLOCKLIST` ou `POSSIBLE_FACE_IN_BLOCKLIST` se déclenche ; `DUPLICATED_FACE` / `POSSIBLE_DUPLICATED_FACE` (`information`) et `MULTIPLE_FACES_DETECTED` (`warning`) ne refusent jamais. Contrairement à la détection passive du vivant, cet endpoint n'exclut **pas** des correspondances les sessions antérieures avec le même `vendor_data`. Une analyse de détection passive du vivant s'exécute également en interne et est stockée avec la session persistée, mais son résultat ne fait pas partie de cette réponse.\n\n**Facturation.** Chaque réponse `200` consomme un crédit d'API de recherche faciale (déduit du crédit de votre forfait ou de votre solde de recharge). Un solde insuffisant renvoie `403` avant tout traitement d'image.\n\n**Persistance de session et enregistrement de visage (`save_api_request`, par défaut `true`).** Lorsque défini sur `true`, l'appel est persisté en tant que session de type API (Business Console, `GET /v3/session/{sessionId}/decision/` via le `request_id` renvoyé, webhook `status.updated`) et le visage recherché est enregistré dans votre index de recherche faciale. Les visages enregistrés par des appels de recherche faciale sont exclus des futurs résultats de recherche faciale, afin que des recherches répétées ne correspondent jamais entre elles. Lorsque défini sur `false`, l'appel est ponctuel : rien n'est stocké, le visage n'est pas enregistré, et les valeurs `match_image_url` sont des chemins de stockage internes plutôt que des URL téléchargeables.\n\n**Sandbox.** Les clés API de sandbox ignorent tout traitement et toute facturation : après la validation de la requête (une entrée malformée renvoie toujours `400`), l'endpoint renvoie un payload fictif statique `Approved`, aucune session n'est persistée et aucun crédit n'est consommé.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou non valides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) — cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes/min par clé API sur l'ensemble des endpoints POST/PATCH/DELETE ; tout dépassement renvoie `429`.",
        "operationId": "post_v3face-search",
        "x-didit-sdk": {
          "resource": "face_search",
          "method": "search",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "user_image"
                ],
                "properties": {
                  "user_image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Image du visage de face avec laquelle effectuer la recherche. Extensions autorisées : `tiff`, `jpg`, `jpeg`, `png`, `webp`. Taille maximale de téléversement : **5 MB** (les fichiers plus volumineux sont rejetés avec une erreur `400`). Les images sont automatiquement compressées à ~0.5 MB avant traitement, de sorte que les très hautes résolutions n'améliorent pas la précision. L'image doit contenir au moins un visage détectable — sinon l'endpoint renvoie `400`. Lorsque plusieurs visages sont présents, la recherche porte sur le plus grand et un avertissement `MULTIPLE_FACES_DETECTED` est ajouté."
                  },
                  "search_type": {
                    "type": "string",
                    "default": "most_similar",
                    "enum": [
                      "most_similar",
                      "blocklisted_or_approved"
                    ],
                    "description": "Règle de recherche. `most_similar` (par défaut) classe chaque visage inscrit dans votre application par similarité. `blocklisted_or_approved` restreint les candidats aux visages sur liste de blocage, sur liste blanche, aux visages issus de sessions approuvées et aux visages de profils d'utilisateurs importés — les entrées sur liste de blocage étant classées en premier.",
                    "example": "most_similar"
                  },
                  "rotate_image": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lorsque la valeur est `true`, le service applique des rotations de 90 degrés à l'image fournie et utilise l'orientation qui produit la meilleure détection faciale. Utile lorsque l'orientation EXIF est manquante. Ajoute de la latence.",
                    "example": false
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Lorsque la valeur est `true` (par défaut), conserve l'appel sous forme de session de type API, émet un webhook `status.updated`, pré-signe les valeurs `match_image_url` et inscrit le visage recherché dans votre index de Recherche faciale (les inscriptions à la Recherche faciale sont exclues des recherches futures). Lorsque la valeur est `false`, la recherche est ponctuelle — aucune session n'est stockée et le visage n'est pas inscrit.",
                    "example": true
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Identifiant opaque optionnel (votre identifiant d'utilisateur, e-mail, UUID…) stocké sur la session persistée et renvoyé. Il n'exclut pas les visages du même utilisateur des résultats de recherche.",
                    "example": "user-123"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Objet JSON optionnel stocké avec la session (lorsque `save_api_request=true`) et renvoyé. Dans les requêtes multipart, envoyez-le sous forme de champ textuel encodé en JSON — il est analysé sous forme d'objet.",
                    "example": {
                      "flow": "dedup_check"
                    }
                  }
                }
              },
              "example": {
                "user_image": "(binary JPEG/PNG selfie)",
                "search_type": "most_similar",
                "rotate_image": false,
                "save_api_request": true,
                "vendor_data": "user-123",
                "metadata": {
                  "flow": "dedup_check"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recherche faciale terminée. `face_search.matches` contient jusqu'à 5 visages similaires classés par similarité ; un tableau vide signifie qu'aucun visage enregistré n'a dépassé le seuil minimal de similarité. `status` est `Declined` uniquement en cas de correspondance avec une liste de blocage — les correspondances en doublon seules renvoient `Approved`, inspectez donc `matches` et `warnings`, pas seulement `status`. Lorsque `save_api_request=true`, `request_id` est l'identifiant de la session conservée. Chaque correspondance contient `source` (`session`, `imported`, `list_entry` ou `retained_template`), `vendor_user_id` et `biometric_template_id` ; une correspondance `retained_template` provient d'un gabarit biométrique sans image conservé après la suppression de la session source et présente des champs de session, `match_image_url` et `user_details` à `null`.",
            "content": {
              "application/json": {
                "examples": {
                  "Blocklist hit (Declined)": {
                    "summary": "Le visage correspond à un visage figurant sur une liste de blocage",
                    "value": {
                      "request_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
                      "face_search": {
                        "status": "Declined",
                        "total_matches": 1,
                        "matches": [
                          {
                            "session_id": "882c42d5-8a4d-4d20-8080-a22f57822c86",
                            "session_number": 323442,
                            "similarity_percentage": 99.99,
                            "source": "session",
                            "vendor_data": "user-1",
                            "verification_date": "2025-01-01T00:00:00Z",
                            "user_details": {
                              "full_name": "Jane Marie Doe",
                              "document_type": "ID",
                              "document_number": "X1234567"
                            },
                            "match_image_url": "https://<media-host>/face/3f6a1c2e/reference.jpg",
                            "status": "Approved",
                            "is_blocklisted": true,
                            "is_allowlisted": false,
                            "api_service": null,
                            "vendor_user_id": "2f7c1a9e-8b4d-4c6a-9e1f-3d5b7a9c1e2f",
                            "biometric_template_id": null
                          }
                        ],
                        "user_image": {
                          "entities": [
                            {
                              "bbox": [
                                40,
                                40,
                                120,
                                120
                              ],
                              "confidence": 0.732973
                            }
                          ],
                          "best_angle": 0
                        },
                        "warnings": [
                          {
                            "risk": "FACE_IN_BLOCKLIST",
                            "feature": "LIVENESS",
                            "additional_data": {
                              "blocklisted_session_id": "882c42d5-8a4d-4d20-8080-a22f57822c86",
                              "blocklisted_session_number": 323442,
                              "api_service": null
                            },
                            "log_type": "error",
                            "short_description": "Face in blocklist",
                            "long_description": "The system identified a face in the blocklist, which means the face is not allowed to be verified."
                          }
                        ]
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T01:04:42.763237+00:00"
                    }
                  },
                  "Duplicate found (Approved)": {
                    "summary": "Le visage est déjà apparu dans une autre session approuvée — informatif, aucun refus",
                    "value": {
                      "request_id": "5e0c3a1f-7b2d-4c8e-9f10-2a3b4c5d6e7f",
                      "face_search": {
                        "status": "Approved",
                        "total_matches": 1,
                        "matches": [
                          {
                            "session_id": "1f2e3d4c-5b6a-7980-1122-334455667788",
                            "session_number": 1024,
                            "similarity_percentage": 87.42,
                            "source": "session",
                            "vendor_data": "user-9",
                            "verification_date": "2025-11-20T09:15:00Z",
                            "user_details": null,
                            "match_image_url": "https://<media-host>/face/9c8b7a6d/reference.jpg",
                            "status": "Approved",
                            "is_blocklisted": false,
                            "is_allowlisted": false,
                            "api_service": "PASSIVE_LIVENESS",
                            "vendor_user_id": "2f7c1a9e-8b4d-4c6a-9e1f-3d5b7a9c1e2f",
                            "biometric_template_id": null
                          }
                        ],
                        "user_image": {
                          "entities": [
                            {
                              "bbox": [
                                40,
                                40,
                                120,
                                120
                              ],
                              "confidence": 0.732973
                            }
                          ],
                          "best_angle": 0
                        },
                        "warnings": [
                          {
                            "risk": "DUPLICATED_FACE",
                            "feature": "LIVENESS",
                            "additional_data": {
                              "duplicated_session_id": "1f2e3d4c-5b6a-7980-1122-334455667788",
                              "duplicated_session_number": 1024,
                              "api_service": "PASSIVE_LIVENESS"
                            },
                            "log_type": "information",
                            "short_description": "Duplicated face from other approved session",
                            "long_description": "The system identified a duplicated face from another approved session, requiring further investigation."
                          }
                        ]
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T01:04:42.763237+00:00"
                    }
                  },
                  "No matches (Approved)": {
                    "summary": "Aucun visage enregistré n'a dépassé le seuil minimal de similarité",
                    "value": {
                      "request_id": "9d8c7b6a-5f4e-3d2c-1b0a-998877665544",
                      "face_search": {
                        "status": "Approved",
                        "total_matches": 0,
                        "matches": [],
                        "user_image": {
                          "entities": [
                            {
                              "bbox": [
                                40,
                                40,
                                120,
                                120
                              ],
                              "confidence": 0.732973
                            }
                          ],
                          "best_angle": 0
                        },
                        "warnings": []
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T01:04:42.763237+00:00"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "face_search": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "Declined"
                          ],
                          "description": "`Declined` uniquement lorsqu'un avertissement `FACE_IN_BLOCKLIST` ou `POSSIBLE_FACE_IN_BLOCKLIST` s'est déclenché. Les correspondances en double et les avertissements de visages multiples n'entraînent jamais de refus."
                        },
                        "total_matches": {
                          "type": "integer",
                          "description": "Nombre d'entrées dans `matches` (0–5).",
                          "example": 1
                        },
                        "matches": {
                          "type": "array",
                          "maxItems": 5,
                          "description": "Jusqu'à 5 visages de votre index de recherche faciale dépassant le seuil de similarité, classés par similarité (avec les entrées sur liste de blocage classées en premier lorsque `search_type=blocklisted_or_approved`). Vide lorsqu'aucun visage enregistré n'est suffisamment similaire.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "session_id": {
                                "type": "string",
                                "format": "uuid",
                                "nullable": true,
                                "description": "Identifiant de la session de vérification à laquelle appartient le visage correspondant. `null` lorsque `source` vaut `imported`, `list_entry` ou `retained_template`.",
                                "example": "882c42d5-8a4d-4d20-8080-a22f57822c86"
                              },
                              "session_number": {
                                "type": "integer",
                                "nullable": true,
                                "description": "Numéro de session lisible par l'humain affiché dans la Business Console. `null` pour les correspondances hors session.",
                                "example": 323442
                              },
                              "similarity_percentage": {
                                "type": "number",
                                "format": "float",
                                "minimum": 0,
                                "maximum": 100,
                                "description": "Similarité entre le visage soumis et le visage correspondant (0–100).",
                                "example": 99.99
                              },
                              "source": {
                                "type": "string",
                                "enum": [
                                  "session",
                                  "imported",
                                  "list_entry",
                                  "retained_template"
                                ],
                                "description": "Provenance de l'enrôlement du visage correspondant : `session` — une session de vérification ou un appel API autonome enregistré ; `imported` — un visage téléversé directement sur un profil utilisateur ; `list_entry` — un visage associé à l'une de vos listes ; `retained_template` — un gabarit biométrique sans image associé à un utilisateur, répertorié sous `/v3/biometric-templates/`."
                              },
                              "vendor_data": {
                                "type": "string",
                                "nullable": true,
                                "description": "`vendor_data` de la session correspondante ou de l'utilisateur lié pour les visages importés et les gabarits conservés.",
                                "example": "user-1"
                              },
                              "vendor_user_id": {
                                "type": "string",
                                "format": "uuid",
                                "nullable": true,
                                "description": "Identifiant de l'utilisateur associé. `null` pour les entrées de liste et les correspondances de session sans utilisateur.",
                                "example": "2f7c1a9e-4b28-4a6d-97f1-83576f80e1b4"
                              },
                              "biometric_template_id": {
                                "type": "string",
                                "format": "uuid",
                                "nullable": true,
                                "description": "Identifiant du gabarit biométrique conservé. Renseigné uniquement lorsque `source` vaut `retained_template` ; `null` sinon.",
                                "example": null
                              },
                              "verification_date": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true,
                                "description": "Moment où le visage correspondant a été initialement capturé, ou lorsqu'un gabarit conservé a été créé (`YYYY-MM-DDThh:mm:ssZ`). `null` pour les correspondances `list_entry`.",
                                "example": "2025-01-01T00:00:00Z"
                              },
                              "user_details": {
                                "type": "object",
                                "nullable": true,
                                "description": "Données d'identité extraites lors de la vérification de document de la session correspondante. `null` lorsque la session correspondante n'a pas de données de document (par exemple, sessions avec détection du vivant uniquement) et toujours `null` pour les correspondances `retained_template`. Pour les correspondances avec `source: imported`, elles sont renseignées à partir du profil utilisateur : `full_name` est défini, `document_type`/`document_number` sont nuls.",
                                "properties": {
                                  "full_name": {
                                    "type": "string",
                                    "nullable": true,
                                    "example": "Jane Marie Doe"
                                  },
                                  "document_type": {
                                    "type": "string",
                                    "nullable": true,
                                    "example": "ID"
                                  },
                                  "document_number": {
                                    "type": "string",
                                    "nullable": true,
                                    "example": "X1234567"
                                  }
                                }
                              },
                              "match_image_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "URL temporaire (`https://<media-host>/...`) de l'image de référence du visage correspondant lorsque `save_api_request=true`. Avec `save_api_request=false`, il s'agit d'un chemin de stockage interne qui n'est pas directement téléchargeable. Vaut toujours `null` pour les correspondances de `retained_template`, car les gabarits conservés ne contiennent aucune image.",
                                "example": "https://<media-host>/face/3f6a1c2e/reference.jpg"
                              },
                              "status": {
                                "type": "string",
                                "nullable": true,
                                "description": "Statut de la session correspondante (`Approved`, `Declined`, `In Review`, …). `null` pour les correspondances `imported`/`list_entry`.",
                                "example": "Approved"
                              },
                              "is_blocklisted": {
                                "type": "boolean",
                                "description": "`true` lorsque le visage correspondant figure sur votre liste de blocage de visages. Toute correspondance suffisamment similaire présente sur la liste de blocage entraîne le refus de la recherche."
                              },
                              "is_allowlisted": {
                                "type": "boolean",
                                "description": "`true` lorsque le visage correspondant figure sur l'une de vos listes d'autorisation. Les correspondances figurant sur liste d'autorisation suppriment les avertissements de doublon."
                              },
                              "api_service": {
                                "type": "string",
                                "nullable": true,
                                "description": "Défini lorsque le visage correspondant a été enrôlé par un appel d'API autonome (par ex. `PASSIVE_LIVENESS`) ; `null` pour les sessions de vérification standard et les visages importés.",
                                "example": null
                              }
                            }
                          }
                        },
                        "user_image": {
                          "type": "object",
                          "description": "Résultats de la détection faciale pour l'image soumise. Les entrées ici ne comportent que `bbox` et `confidence`.",
                          "properties": {
                            "entities": {
                              "type": "array",
                              "description": "Une entrée par visage détecté. Le visage le plus grand est celui qui est recherché.",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "bbox": {
                                    "type": "array",
                                    "items": {
                                      "type": "integer"
                                    },
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "description": "Boîte englobante `[x_min, y_min, x_max, y_max]` en pixels.",
                                    "example": [
                                      40,
                                      40,
                                      120,
                                      120
                                    ]
                                  },
                                  "confidence": {
                                    "type": "number",
                                    "format": "float",
                                    "minimum": 0,
                                    "maximum": 1,
                                    "description": "Indice de confiance de la détection faciale (0–1).",
                                    "example": 0.732973
                                  }
                                }
                              }
                            },
                            "best_angle": {
                              "type": "integer",
                              "description": "Rotation (en degrés) ayant produit la meilleure détection de visage ; non nulle uniquement lorsque `rotate_image=true` a corrigé l'orientation. N'est jamais null sur cet endpoint (prend la valeur 0 par défaut lorsque le modèle l'omet).",
                              "example": 0
                            }
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "description": "Signaux de risque. `FACE_IN_BLOCKLIST` / `POSSIBLE_FACE_IN_BLOCKLIST` (`error`) refusent la recherche ; `MULTIPLE_FACES_DETECTED` (`warning`) et `DUPLICATED_FACE` / `POSSIBLE_DUPLICATED_FACE` (`information`) sont informatifs.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "risk": {
                                "type": "string",
                                "enum": [
                                  "MULTIPLE_FACES_DETECTED",
                                  "FACE_IN_BLOCKLIST",
                                  "POSSIBLE_FACE_IN_BLOCKLIST",
                                  "DUPLICATED_FACE",
                                  "POSSIBLE_DUPLICATED_FACE"
                                ],
                                "description": "Code de risque lisible par machine."
                              },
                              "feature": {
                                "type": "string",
                                "enum": [
                                  "LIVENESS"
                                ],
                                "description": "Fonctionnalité ayant émis l'avertissement. Toujours `LIVENESS` sur cet endpoint."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "additionalProperties": true,
                                "description": "`null` pour `MULTIPLE_FACES_DETECTED`. Les correspondances avec la liste de blocage comportent `{blocklisted_session_id, blocklisted_session_number, api_service}` ; les correspondances de doublons comportent `{duplicated_session_id, duplicated_session_number, api_service}` pointant vers la première session correspondante."
                              },
                              "log_type": {
                                "type": "string",
                                "enum": [
                                  "error",
                                  "warning",
                                  "information"
                                ],
                                "description": "Gravité. Les avertissements `error` font passer `status` à `Declined` ; les entrées `warning` et `information` sont indicatives et ne refusent jamais d'elles-mêmes."
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Résumé du risque en une ligne, lisible par l'utilisateur."
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication lisible par l'humain du risque."
                              }
                            }
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Écho des `vendor_data` que vous avez envoyées, ou `null`."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Écho de l'objet `metadata` que vous avez envoyé, ou `null`."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Horodatage ISO 8601 (UTC) du moment où la réponse a été générée, ex. `2026-06-12T01:04:42.763237+00:00`."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Renvoyée lorsque `user_image` est manquant, dépasse 5 Mo, possède une extension non prise en charge, ou lorsque **aucun visage n'est détecté** dans l'image soumise. Les erreurs de champ utilisent l'enveloppe `{field: [messages]}` de DRF ; les échecs de détection de visage utilisent `{\"error\": ...}`.",
            "content": {
              "application/json": {
                "examples": {
                  "No face detected": {
                    "summary": "L'image se décode correctement mais ne contient aucun visage détectable",
                    "value": {
                      "error": "No face detected in the image"
                    }
                  },
                  "Missing image": {
                    "summary": "`user_image` non inclus dans les données de formulaire",
                    "value": {
                      "user_image": [
                        "No file was submitted."
                      ]
                    }
                  },
                  "Unsupported file extension": {
                    "summary": "Extension de fichier autre que tiff/jpg/jpeg/png/webp",
                    "value": {
                      "user_image": [
                        "File extension “txt” is not allowed. Allowed extensions are: tiff, jpg, jpeg, png, webp."
                      ]
                    }
                  },
                  "File too large": {
                    "summary": "Le téléversement dépasse la limite de 5 MB",
                    "value": {
                      "user_image": [
                        "File size should not exceed 5 MB"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout traitement d'image.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/face-search/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'user_image=@./selfie.jpg' \\\n  -F 'search_type=most_similar' \\\n  -F 'save_api_request=true' \\\n  -F 'vendor_data=user-123'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.face_search.search(\n    user_image=open(\"user_image.jpg\", \"rb\"),\n    search_type=\"most_similar\",\n    rotate_image=False,\n    save_api_request=True,\n    vendor_data=\"user-123\",\n    metadata={\"flow\": \"dedup_check\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.faceSearch.search({\n  user_image: await fileFromPath(\"user_image.jpg\"),\n  search_type: \"most_similar\",\n  rotate_image: false,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"dedup_check\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.FaceSearch.Search(ctx, didit.FaceSearchSearchParams{\n\tUserImage:      didit.FileFromPath(\"user_image.jpg\"),\n\tSearchType:     didit.Some(didit.FaceSearchSearchParamsSearchType(\"most_similar\")),\n\tRotateImage:    didit.Bool(false),\n\tSaveAPIRequest: didit.Bool(true),\n\tVendorData:     didit.String(\"user-123\"),\n\tMetadata:       didit.Some(map[string]any{\"flow\": \"dedup_check\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.FaceSearchSearchParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.faceSearch().search(FaceSearchSearchParams.builder()\n        .userImage(Path.of(\"user_image.jpg\"))\n        .searchType(FaceSearchSearchParams.SearchType.of(\"most_similar\"))\n        .rotateImage(false)\n        .saveApiRequest(true)\n        .vendorData(\"user-123\")\n        .metadata(Map.of(\"flow\", \"dedup_check\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->faceSearch->search([\n    'user_image' => File::fromPath('user_image.jpg'),\n    'search_type' => 'most_similar',\n    'rotate_image' => false,\n    'save_api_request' => true,\n    'vendor_data' => 'user-123',\n    'metadata' => ['flow' => 'dedup_check'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.face_search.search(\n  user_image: Pathname(\"user_image.jpg\"),\n  search_type: \"most_similar\",\n  rotate_image: false,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"dedup_check\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.FaceSearch.SearchAsync(new FaceSearchSearchParams\n{\n    UserImage = FileUpload.FromPath(\"user_image.jpg\"),\n    SearchType = new FaceSearchSearchParamsSearchType(\"most_similar\"),\n    RotateImage = false,\n    SaveApiRequest = true,\n    VendorData = \"user-123\",\n    Metadata = new Dictionary<string, object> { [\"flow\"] = \"dedup_check\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/sessions/": {
      "get": {
        "summary": "Lister les sessions de vérification (KYC et/ou KYB) avec filtres et pagination",
        "description": "Renvoie une liste paginée de sessions de vérification pour l'application identifiée par votre clé API, les plus récentes en premier (`session_number` décroissant).\n\n**URL canonique :** la route est `/v3/sessions/` (slash final). Les requêtes vers `/v3/sessions` sans le slash reçoivent une redirection `301` vers l'URL avec slash en conservant la chaîne de requête ; la plupart des clients HTTP la suivent de manière transparente sur GET.\n\n**Quand utiliser cet endpoint par rapport aux webhooks.** Utilisez cet endpoint pour les tableaux de bord, la recherche dans le back-office, le rapprochement et les exports par lot. Ne l'interrogez pas en boucle pour suivre la progression de vérifications individuelles - configurez plutôt des [webhooks](/fr/integration/webhooks), qui envoient des événements `status.updated` dès qu'une session change. Pour obtenir le résultat complet d'une session, appelez `GET /v3/session/{sessionId}/decision/`.\n\n**Sessions KYC et KYB.** `session_kind` sélectionne les types répertoriés :\n- `user` (par défaut) - sessions de Vérification des utilisateurs (KYC) uniquement. Comportement rétrocompatible.\n- `business` - sessions de Vérification d'entreprise (KYB) uniquement. Les lignes ont une structure différente et plus compacte (voir le schéma de réponse).\n- `all` - les deux types dans une seule réponse : la page KYC et la page KYB pour les mêmes valeurs de `limit`/`offset` sont concaténées dans `results` (les lignes KYC en premier), de sorte qu'une page peut contenir jusqu'à `2 x limit` lignes. `count` est la somme des deux types et `next`/`previous` reflètent la pagination côté KYC. Pour une pagination stricte de données mixtes, appelez `user` et `business` séparément.\n\nChaque ligne comporte un discriminateur `session_kind` (`\"user\"` ou `\"business\"`).\n\n**Pagination.** Limit/offset standard : `limit` (50 par défaut) et `offset` (0 par défaut), avec des URL de pages prêtes à l'emploi dans `next`/`previous`. Pour les lignes KYC, `count` est exact. Pour les lignes KYB, `count` est calculé avec un balayage borné et est plafonné à 100 - lorsqu'il y a plus de 100 correspondances, il reste à 100 ; itérez donc à l'aide de `next` (ou en vérifiant si une page complète a été renvoyée) plutôt qu'en calculant le nombre total de pages à partir de `count`.\n\n**Sémantique des filtres.** Tous les filtres se combinent avec ET et s'appliquent aux lignes KYC. Lorsque `session_kind` vaut `business` ou `all`, le côté KYB prend en compte les paramètres partagés `vendor_data`, `status`, `workflow_id`, `country` (code pays du registre des sociétés), `date_from`, `date_to`, `search` (nom de l'entreprise, numéro d'immatriculation - saisissez les numéros d'immatriculation sans séparateurs, par exemple `DPC001` et non `DPC-001` - vendor_data, numéro de session ou UUID de session), `warning` et `organization_name` ; les autres filtres réservés au KYC sont ignorés pour les lignes KYB. Les paramètres séparés par des virgules (`status`, `country`, `document_type`, `region`, `workflow_id`, `document_name`, `warning`, `organization_name`, `session_type`) correspondent à l'une quelconque des valeurs listées (OU au sein du paramètre). `vendor_data` est une correspondance exacte - utilisez `search` pour une correspondance partielle. Les valeurs inconnues dans les filtres de liste ne renvoient simplement aucune ligne (aucune erreur) ; les valeurs typées mal formées (`date_from`, `date_to`, `didit_internal_id`, `api_service`, `session_kind`) renvoient `400` avec un objet d'erreur par champ.\n\n**Recherche.** `search` s'adapte à la saisie : un UUID complet recherche `session_id` ; les chiffres (avec `+ - . space` facultatifs) correspondent au préfixe du numéro de session, aux numéros de document et aux numéros personnels, au préfixe de numéro de téléphone ou à `vendor_data` ; les valeurs contenant `@` correspondent aux préfixes d'e-mail ; tout autre texte correspond aux noms (insensible aux accents) et à `vendor_data`.\n\nAucune limite de débit fixe par endpoint n'est appliquée, mais évitez d'interroger la liste trop fréquemment et appuyez-vous sur les webhooks pour les mises à jour en temps réel.",
        "operationId": "get_v3_sessions",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "session_kind",
            "in": "query",
            "required": false,
            "description": "Quel type de sessions lister : `user` (KYC uniquement, par défaut), `business` (KYB uniquement) ou `all` (les deux, concaténées - voir la description pour la sémantique de pagination fusionnée). La correspondance est insensible à la casse (`BUSINESS` fonctionne) ; toute valeur autre qu'une variante de casse de `user`/`business`/`all` renvoie `400`.",
            "schema": {
              "type": "string",
              "enum": [
                "user",
                "business",
                "all"
              ],
              "default": "user"
            },
            "example": "all"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Nombre maximal de lignes par page (par type lorsque `session_kind=all`). Vaut par défaut 50.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "example": 20
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Nombre de lignes à ignorer avant la première ligne retournée. La valeur par défaut est 0. Privilégiez l'utilisation des URL `next`/`previous` de la réponse.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "example": 20
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Liste séparée par des virgules des statuts de session à inclure, par exemple `Approved,In Review`. Les valeurs sont sensibles à la casse ; voir [Statuts de vérification](/fr/integration/verification-statuses). Les valeurs inconnues ne correspondent à aucun élément.",
            "schema": {
              "type": "string"
            },
            "example": "Approved,In Review"
          },
          {
            "name": "vendor_data",
            "in": "query",
            "required": false,
            "description": "Filtre par correspondance exacte sur le `vendor_data` que vous avez envoyé lors de la création de la session (votre propre identifiant d'utilisateur/d'entreprise). Pour les correspondances partielles, utilisez plutôt `search`.",
            "schema": {
              "type": "string"
            },
            "example": "your-user-id-123"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Une référence affichée complète telle que `S-0001` (utilisateur) ou `B-0001` (entreprise) correspond uniquement à ce numéro et à ce type de session ; les zéros de tête et la casse des lettres n'affectent pas la correspondance. Recherche intelligente en texte libre. Un UUID complet correspond à `session_id` ; une saisie numérique correspond à un préfixe de numéro de session, aux numéros de document/personnels, à un préfixe de téléphone ou à `vendor_data` ; une saisie contenant `@` correspond aux préfixes d'e-mail ; les autres textes correspondent aux noms (insensible aux accents) et à `vendor_data`. Le texte libre contenant des chiffres correspond en plus aux champs de recherche de numéros de document/personnels et aux préfixes de numéros de session.",
            "schema": {
              "type": "string"
            },
            "example": "jane doe"
          },
          {
            "name": "workflow_id",
            "in": "query",
            "required": false,
            "description": "UUID de workflow séparés par des virgules (retrouvez-les sur la page Workflows de la console). Les UUID mal formés dans la liste sont ignorés ; si aucun n'est valide, le résultat est vide.",
            "schema": {
              "type": "string"
            },
            "example": "9f9b1234-aaaa-bbbb-cccc-1234567890ab"
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "description": "Uniquement les sessions créées à partir de cette date (UTC) incluse, au format `YYYY-MM-DD`. Les dates mal formées renvoient `400`.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-06-01"
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "description": "Uniquement les sessions créées jusqu'à cette date (UTC) incluse, au format `YYYY-MM-DD`. Pour les lignes KYC, la journée entière est incluse ; pour les lignes KYB, la comparaison est `created_at <= date_to` (minuit), utilisez donc la date du jour suivant pour inclure une journée complète de sessions KYB.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-06-30"
          },
          {
            "name": "tags",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Identifiants de tags séparés par des virgules (`tags` de votre application). Renvoie les sessions portant l'un d'entre eux. Les identifiants qui ne sont pas des UUID valides sont ignorés, et si aucun n'est valide, la liste est vide."
          },
          {
            "name": "decided_from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Date et heure ISO 8601. Renvoie les sessions dont le statut a changé pour la dernière fois à cette date ou après celle-ci. Filtre sur l'heure du dernier changement de statut, et non sur l'heure de création."
          },
          {
            "name": "decided_to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Date et heure ISO 8601. Renvoie les sessions dont le statut a changé pour la dernière fois avant cette date. À combiner avec `decided_from` pour obtenir une période semi-ouverte."
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Filtre de pays séparés par des virgules. Pour les lignes KYC : codes ISO 3166-1 alpha-3 de l'État de délivrance du document d'identité (par ex. `ESP,USA`), qui peuvent différer de la nationalité. Pour les lignes KYB : code du pays de l'entreprise enregistrée.",
            "schema": {
              "type": "string"
            },
            "example": "ESP,USA"
          },
          {
            "name": "document_type",
            "in": "query",
            "required": false,
            "description": "Codes des types de documents d'identité vérifiés au cours de la session, séparés par des virgules (lignes KYC uniquement) : `P` (passeport), `ID` (carte d'identité), `DL` (permis de conduire), `RP` (titre de séjour), `SSC` (carte de sécurité sociale), `HIC` (carte d'assurance maladie), `WP` (permis de travail), `TC` (carte fiscale), `VISA`, `PSC` (carte de service public), `BC` (acte de naissance), `OTHER`. Notez que le champ de réponse `document_type` contient le nom d'affichage, et non le code.",
            "schema": {
              "type": "string"
            },
            "example": "P,ID"
          },
          {
            "name": "document_name",
            "in": "query",
            "required": false,
            "description": "Noms exacts des documents ; plusieurs noms peuvent être transmis séparés par des virgules, mais la valeur n'est scindée sur les virgules que lorsqu'elle contient plus d'un séparateur ` - ` (un nom unique contenant une virgule est mis en correspondance dans son intégralité). Les noms sont tels que reconnus par la vérification de documents (recto ou verso), par ex. `Spain - Id Card (2021)`. Lignes KYC uniquement.",
            "schema": {
              "type": "string"
            },
            "example": "Spain - Id Card (2021)"
          },
          {
            "name": "region",
            "in": "query",
            "required": false,
            "description": "Valeurs de région/État du document séparées par des virgules (pour les documents délivrés par région, comme les permis de conduire américains). Lignes KYC uniquement.",
            "schema": {
              "type": "string"
            },
            "example": "CA,TX"
          },
          {
            "name": "didit_internal_id",
            "in": "query",
            "required": false,
            "description": "Filtrer par identifiant d'utilisateur interne Didit (le champ de réponse `didit_internal_id`) pour lister toutes les sessions d'un utilisateur vérifié. Doit être un UUID valide ; les valeurs malformées renvoient `400`. Lignes KYC uniquement.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "d9e78474-6c8d-4f2a-bb90-6f5c2f3a1147"
          },
          {
            "name": "session_type",
            "in": "query",
            "required": false,
            "description": "Canaux de création de session séparés par des virgules : `API`, `HOSTED`, `MIGRATED`. La valeur spéciale `ALL` (ou l'omission du paramètre) désactive le filtre. Lignes KYC uniquement.",
            "schema": {
              "type": "string"
            },
            "example": "HOSTED"
          },
          {
            "name": "api_service",
            "in": "query",
            "required": false,
            "description": "Filtrer les sessions d'API autonomes par service. Les valeurs non valides renvoient `400`. Lignes KYC uniquement.",
            "schema": {
              "type": "string",
              "enum": [
                "ID_VERIFICATION",
                "FACE_MATCH",
                "AGE_ESTIMATION",
                "FACE_SEARCH",
                "POA",
                "AML",
                "KYB_REGISTRY",
                "PASSIVE_LIVENESS",
                "DATABASE_VALIDATION",
                "PHONE_VERIFICATION",
                "EMAIL_VERIFICATION"
              ]
            },
            "example": "AML"
          },
          {
            "name": "screened_full_name",
            "in": "query",
            "required": false,
            "description": "Recherche de nom insensible aux accents parmi les données filtrées d'AML et de validation en base de données. Combinée avec `api_service=AML` ou `api_service=DATABASE_VALIDATION`, la recherche est limitée aux données filtrées de cette fonctionnalité. Lignes KYC uniquement.",
            "schema": {
              "type": "string"
            },
            "example": "Jane Doe"
          },
          {
            "name": "warning",
            "in": "query",
            "required": false,
            "description": "Codes de risque d'avertissement séparés par des virgules ; renvoie les sessions ayant déclenché l'un d'entre eux (par ex. `POSSIBLE_FRAUD`). Les codes de risque sont répertoriés par fonctionnalité dans la [documentation des avertissements](/fr/integration/webhooks). S'applique aux lignes KYC et, avec les codes d'avertissement d'entreprise, aux lignes KYB.",
            "schema": {
              "type": "string"
            },
            "example": "POSSIBLE_FRAUD"
          },
          {
            "name": "status_initialized_as_in_review",
            "in": "query",
            "required": false,
            "description": "Lorsque la valeur est `true`, seules les sessions dont la décision a initialement abouti à `In Review` (utile pour auditer le volume d'examens manuels). Lignes KYC uniquement.",
            "schema": {
              "type": "boolean"
            },
            "example": true
          },
          {
            "name": "is_kyc_to_be_reviewed",
            "in": "query",
            "required": false,
            "description": "`true` renvoie les sessions dont la vérification du document est marquée pour examen manuel ; `false` renvoie les sessions dont la vérification du document n'est explicitement pas marquée. Omettre pour désactiver. Lignes KYC uniquement.",
            "schema": {
              "type": "boolean"
            },
            "example": true
          },
          {
            "name": "euuid",
            "in": "query",
            "required": false,
            "description": "Filtrer par l'euuid de l'utilisateur final (UUID assigné à l'utilisateur en cours de vérification, utilisé par les liens profonds de la Console). Doit être un UUID valide ; les valeurs incorrectes renvoient une erreur de champ 400. Lignes KYC uniquement.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "0f8fad5b-d9cb-469f-a165-70867728950e"
          },
          {
            "name": "organization_name",
            "in": "query",
            "required": false,
            "description": "Noms d'organisations séparés par des virgules. Destiné à la console ; avec une clé API (déjà limitée à une seule application), il ne correspond qu'au nom de votre propre organisation.",
            "schema": {
              "type": "string"
            },
            "example": "Acme Inc"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginée de sessions. Les éléments de `results` sont des lignes KYC, des lignes KYB, ou les deux selon `session_kind` ; différenciez-les grâce au champ `session_kind` de chaque ligne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de sessions correspondant aux filtres : exact jusqu'à 100 et plafonné à 100 au-delà, ne l'utilisez donc pas comme un total. Utilisez `next` pour savoir si d'autres pages existent. Pour `session_kind=all`, il s'agit de la somme des deux types, chacun plafonné à 100.",
                      "example": 2
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page.",
                      "example": "https://verification.didit.me/v3/sessions/?limit=20&offset=20"
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page.",
                      "example": null
                    },
                    "results": {
                      "type": "array",
                      "description": "Lignes de session, les plus récentes en premier. Avec `session_kind=all`, les lignes KYC apparaissent en premier, puis les lignes KYB.",
                      "items": {
                        "oneOf": [
                          {
                            "$ref": "#/components/schemas/UserSessionListItem"
                          },
                          {
                            "$ref": "#/components/schemas/BusinessSessionListItem"
                          }
                        ],
                        "discriminator": {
                          "propertyName": "session_kind",
                          "mapping": {
                            "user": "#/components/schemas/UserSessionListItem",
                            "business": "#/components/schemas/BusinessSessionListItem"
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "KYC sessions (default)": {
                    "summary": "session_kind=user - une session terminée et une session non démarrée",
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "session_id": "5b3720ed-d429-42ef-b67f-37ea805f48ee",
                          "session_kind": "user",
                          "session_number": 720,
                          "session_url": "https://verify.didit.me/session/CuXoBYCYVO5Y",
                          "portrait_image": "https://<media-host>/portraits/5b3720ed.jpg?X-Amz-Expires=3600&X-Amz-Signature=...",
                          "document_type": "Passport",
                          "full_name": "Jane Marie Doe",
                          "country": "ESP",
                          "status": "Approved",
                          "vendor_data": "your-user-id-123",
                          "didit_internal_id": "d9e78474-6c8d-4f2a-bb90-6f5c2f3a1147",
                          "created_at": "2026-06-09T12:26:54.328364Z",
                          "features": [
                            {
                              "feature": "ID_VERIFICATION",
                              "status": "Approved"
                            },
                            {
                              "feature": "LIVENESS",
                              "status": "Approved"
                            },
                            {
                              "feature": "FACE_MATCH",
                              "status": "Approved"
                            },
                            {
                              "feature": "AML",
                              "status": "Approved"
                            },
                            {
                              "feature": "IP_ANALYSIS",
                              "status": "Approved"
                            }
                          ],
                          "phone_number": {
                            "number": "+14155552671",
                            "is_verified": true
                          },
                          "email_address": {
                            "email": "jane@example.com",
                            "is_verified": true
                          },
                          "additional_details": {
                            "aml": {
                              "total_hits": 0,
                              "entity_type": "person",
                              "is_adverse_media_fetched": false
                            },
                            "liveness": {
                              "method": "PASSIVE",
                              "score": 0.98
                            },
                            "face_match": {
                              "score": 0.95
                            }
                          }
                        },
                        {
                          "session_id": "038ad62f-5ebd-46c2-afe9-4b2956bf687f",
                          "session_kind": "user",
                          "session_number": 719,
                          "session_url": "https://verify.didit.me/session/7RGKiO6ioGH6",
                          "portrait_image": null,
                          "document_type": null,
                          "full_name": null,
                          "country": null,
                          "status": "Not Started",
                          "vendor_data": "your-user-id-124",
                          "didit_internal_id": "eb4e679d-ca4b-461f-9685-687bac29ebdb",
                          "created_at": "2026-06-09T08:02:23.343053Z",
                          "features": [
                            {
                              "feature": "ID_VERIFICATION",
                              "status": "Not Finished"
                            },
                            {
                              "feature": "LIVENESS",
                              "status": "Not Finished"
                            },
                            {
                              "feature": "FACE_MATCH",
                              "status": "Not Finished"
                            },
                            {
                              "feature": "AML",
                              "status": "Not Finished"
                            },
                            {
                              "feature": "IP_ANALYSIS",
                              "status": "Not Finished"
                            }
                          ],
                          "phone_number": null,
                          "email_address": null,
                          "additional_details": null
                        }
                      ]
                    }
                  },
                  "Mixed KYC + KYB (session_kind=all)": {
                    "summary": "session_kind=all - ligne KYC suivie d'une ligne KYB",
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "session_id": "5b3720ed-d429-42ef-b67f-37ea805f48ee",
                          "session_kind": "user",
                          "session_number": 720,
                          "session_url": "https://verify.didit.me/session/CuXoBYCYVO5Y",
                          "portrait_image": null,
                          "document_type": "Identity Card",
                          "full_name": "Jane Marie Doe",
                          "country": "ESP",
                          "status": "In Review",
                          "vendor_data": "your-user-id-123",
                          "didit_internal_id": "d9e78474-6c8d-4f2a-bb90-6f5c2f3a1147",
                          "created_at": "2026-06-09T12:26:54.328364Z",
                          "features": [
                            {
                              "feature": "ID_VERIFICATION",
                              "status": "In Review"
                            },
                            {
                              "feature": "LIVENESS",
                              "status": "Approved"
                            }
                          ],
                          "phone_number": null,
                          "email_address": null,
                          "additional_details": {
                            "liveness": {
                              "method": "PASSIVE",
                              "score": 0.98
                            }
                          }
                        },
                        {
                          "session_id": "8a1f63c2-1b9e-4f3a-9c41-2f6a1f0b7d52",
                          "session_kind": "business",
                          "session_number": 42,
                          "status": "Approved",
                          "vendor_data": "your-company-id-77",
                          "created_at": "2026-06-08T09:14:02.118450Z",
                          "workflow_id": "9f9b1234-aaaa-bbbb-cccc-1234567890ab",
                          "workflow_type": "kyb",
                          "workflow_label": "Standard KYB",
                          "company_name": "Acme Holdings S.L.",
                          "registration_number": "B12345678",
                          "country": "ES"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "301": {
            "description": "Redirection vers l'URL canonique avec barre oblique finale. Renvoyée lorsque le chemin de la requête est `/v3/sessions` (sans barre oblique finale) ; l'en-tête `Location` pointe vers `/v3/sessions/` en conservant la chaîne de requête. Les clients GET la suivent généralement de manière automatique."
          },
          "400": {
            "description": "Paramètre de requête non valide. Le corps est un objet indexé par le paramètre en cause.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid session_kind": {
                    "summary": "session_kind n'est pas l'un de user/business/all",
                    "value": {
                      "session_kind": "Must be \"user\", \"business\", or \"all\"."
                    }
                  },
                  "Invalid date": {
                    "summary": "date_from/date_to mal formés",
                    "value": {
                      "date_from": [
                        "Enter a valid date."
                      ]
                    }
                  },
                  "Invalid didit_internal_id": {
                    "summary": "didit_internal_id n'est pas un UUID",
                    "value": {
                      "didit_internal_id": [
                        "Enter a valid UUID."
                      ]
                    }
                  },
                  "Invalid api_service": {
                    "summary": "api_service ne fait pas partie des choix autorisés",
                    "value": {
                      "api_service": [
                        "Select a valid choice. FOO is not one of the available choices."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, malformée ou révoquée. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.\n\n**Application supprimée :** pendant quelques minutes après la suppression d'une application, une requête effectuée avec l'une de ses clés API peut répondre `{\"detail\": \"This application was deleted.\", \"code\": \"application_deleted\"}`. Ne réessayez pas : l'application et ses clés API n'existent plus. Après ces quelques minutes, la clé est refusée comme toute autre clé invalide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "You do not have permission to perform this action."
                    },
                    "code": {
                      "type": "string",
                      "description": "Raison lisible par machine, présente uniquement lors de certains échecs. `application_deleted` : la clé API appartient à une application qui a été supprimée.",
                      "example": "application_deleted"
                    }
                  },
                  "required": [
                    "detail"
                  ]
                },
                "examples": {
                  "Forbidden": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "ApplicationDeleted": {
                    "summary": "Clé API d'une application supprimée",
                    "value": {
                      "detail": "This application was deleted.",
                      "code": "application_deleted"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -s 'https://verification.didit.me/v3/sessions/?status=Approved,In%20Review&date_from=2026-06-01&limit=20' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.sessions.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.sessions.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Sessions.ListAutoPaging(ctx, didit.SessionsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.sessions().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->sessions->list() as $item) {\n    print_r($item);\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.sessions.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Sessions.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/share/": {
      "post": {
        "summary": "Générer un token de partage pour une session de vérification terminée",
        "description": "Générer un JWT à courte durée de vie permettant à une application Didit spécifique d'importer cette session terminée. À associer avec `POST /v3/session/import-shared/`.",
        "operationId": "post_v3_session_share",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "share",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "responses": {
          "200": {
            "description": "Token de partage généré.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "share_token": {
                      "type": "string",
                      "description": "JWT signé avec HS256. Transmettez-le tel quel en tant que `share_token` à [`POST /v3/session/import-shared/`](/sessions-api/import-shared-session) sur l'application cible.",
                      "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                    },
                    "for_application_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Renvoie l'UUID de l'application cible à laquelle le token est associé.",
                      "example": "a5f3bca2-46e2-411e-90ef-a580900a57ee"
                    },
                    "session_kind": {
                      "type": "string",
                      "enum": [
                        "user",
                        "business"
                      ],
                      "description": "Indique si la session source est une session de Vérification des utilisateurs (KYC) ou de Vérification d'entreprise (KYB)."
                    }
                  }
                },
                "examples": {
                  "User session": {
                    "summary": "Partager une session KYC",
                    "value": {
                      "share_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXNzaW9uX2lkIjoiMjBiYjNjM2ItNjE0Ni00MzlmLTg0YTQtYmQzMGQwMGFjNmEyIiwiZnJvbV9hcHBsaWNhdGlvbl9pZCI6ImRiZDIwZTM0LTQyZTktNGYyYy1iYTkxLWNmMDc2MjAxNmY2NCIsImZvcl9hcHBsaWNhdGlvbl9pZCI6ImE1ZjNiY2EyLTQ2ZTItNDExZS05MGVmLWE1ODA5MDBhNTdlZSIsImlhdCI6MTc1MzYzMDY2NiwiZXhwIjoxNzUzNjM0MjY2fQ.JJ9pNE_hqZsOtbR0XYZIWw4JzidjdEl279iUrsIkhGE",
                      "for_application_id": "a5f3bca2-46e2-411e-90ef-a580900a57ee",
                      "session_kind": "user"
                    }
                  },
                  "Business session": {
                    "summary": "Partager une session KYB",
                    "value": {
                      "share_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                      "for_application_id": "a5f3bca2-46e2-411e-90ef-a580900a57ee",
                      "session_kind": "business"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Identifiants manquants ou invalides. Contrairement à la plupart des endpoints v3, cet endpoint s'authentifie via le décorateur d'autorisations et renvoie `401` lorsqu'aucun token ou clé valide n'est présenté.",
            "content": {
              "application/json": {
                "examples": {
                  "Unauthorized": {
                    "summary": "Non autorisé",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session avec le `session_id` indiqué n'existe dans votre application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "Session introuvable",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les erreurs de champ sont indexées par nom de champ ; l'erreur de non-achèvement apparaît sous une clé `detail` (sous forme de tableau).",
            "content": {
              "application/json": {
                "examples": {
                  "Wrong status": {
                    "summary": "La session source n'est pas terminée",
                    "value": {
                      "detail": [
                        "Only finished sessions (\"Approved\", \"Declined\", \"In Review\") can be shared."
                      ]
                    }
                  },
                  "Target missing": {
                    "summary": "L'application cible n'existe pas",
                    "value": {
                      "for_application_id": [
                        "Target application does not exist."
                      ]
                    }
                  },
                  "Self-share": {
                    "summary": "La cible est l'application appelante",
                    "value": {
                      "for_application_id": [
                        "Cannot share a session with the same application."
                      ]
                    }
                  },
                  "TTL bounds": {
                    "summary": "ttl_in_seconds hors limites",
                    "value": {
                      "ttl_in_seconds": [
                        "Ensure this value is greater than or equal to 60."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Les identifiants d'authentification sont valides mais ne disposent pas de l'autorisation `write:sessions` pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "No Permission": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    },
                    "summary": "Aucune autorisation"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification source pour laquelle générer un token.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "for_application_id"
                ],
                "properties": {
                  "for_application_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID de l'application Didit qui échangera le token. Doit exister, ne doit pas être supprimée et doit différer de l'application appelante. Retrouvez-le dans la Business Console sous **Settings → Application**.",
                    "example": "a5f3bca2-46e2-411e-90ef-a580900a57ee"
                  },
                  "ttl_in_seconds": {
                    "type": "integer",
                    "description": "Durée de vie du token, en secondes. Minimum `60`, maximum `86400` (24 h). Vaut par défaut `3600` (1 h).",
                    "minimum": 60,
                    "maximum": 86400,
                    "default": 3600,
                    "example": 3600
                  }
                }
              },
              "example": {
                "for_application_id": "a5f3bca2-46e2-411e-90ef-a580900a57ee",
                "ttl_in_seconds": 7200
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/share/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"for_application_id\": \"a5f3bca2-46e2-411e-90ef-a580900a57ee\",\n    \"ttl_in_seconds\": 7200\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.share(\n    \"11111111-2222-3333-4444-555555555555\",\n    for_application_id=\"a5f3bca2-46e2-411e-90ef-a580900a57ee\",\n    ttl_in_seconds=7200,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.share(\"11111111-2222-3333-4444-555555555555\", {\n  for_application_id: \"a5f3bca2-46e2-411e-90ef-a580900a57ee\",\n  ttl_in_seconds: 7200,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Share(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsShareParams{\n\tForApplicationID: \"a5f3bca2-46e2-411e-90ef-a580900a57ee\",\n\tTTLInSeconds:     didit.Int(7200),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsShareParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().share(\"11111111-2222-3333-4444-555555555555\", SessionsShareParams.builder()\n        .forApplicationId(\"a5f3bca2-46e2-411e-90ef-a580900a57ee\")\n        .ttlInSeconds(7200L)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->share('11111111-2222-3333-4444-555555555555', [\n    'for_application_id' => 'a5f3bca2-46e2-411e-90ef-a580900a57ee',\n    'ttl_in_seconds' => 7200,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.share(\n  \"11111111-2222-3333-4444-555555555555\",\n  for_application_id: \"a5f3bca2-46e2-411e-90ef-a580900a57ee\",\n  ttl_in_seconds: 7200\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.ShareAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsShareParams\n{\n    ForApplicationId = \"a5f3bca2-46e2-411e-90ef-a580900a57ee\",\n    TtlInSeconds = 7200,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/import-shared/": {
      "post": {
        "summary": "Échanger un token de partage pour cloner une session de vérification dans votre application",
        "description": "Échanger un token de partage pour cloner une session KYC ou KYB dans l'application appelante avec un nouveau `session_id`. Non idempotent — un token ne peut être échangé qu'une seule fois par destinataire.",
        "operationId": "post_v3_session_import_shared",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "import_shared",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "responses": {
          "201": {
            "description": "Session clonée. Le corps est le payload de décision V3 pour les deux types, distingués par `session_kind` : `\"user\"` (KYC) avec des blocs de fonctionnalités basés sur des listes tels que `id_verifications`, `liveness_checks`, `aml_screenings` ; `\"business\"` (KYB) avec des blocs tels que `registry_checks` et `key_people_checks`. Tous deux incluent `shared_from_session` — le `session_id` de la session d'origine dans l'application source. Avec `trust_review: false`, le `status` de la session clonée est forcé à `In Review`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionDecision"
                },
                "examples": {
                  "User session imported": {
                    "summary": "Session KYC clonée (tronquée — payload de décision V3 complet en réalité)",
                    "value": {
                      "session_id": "11111111-2222-3333-4444-555555555555",
                      "session_kind": "user",
                      "shared_from_session": "99999999-8888-7777-6666-555555555555",
                      "session_number": 43762,
                      "session_url": null,
                      "status": "In Review",
                      "workflow_id": "9f9b1234-aaaa-bbbb-cccc-1234567890ab",
                      "vendor_data": "user-1",
                      "created_at": "2026-05-17T08:42:11Z",
                      "expires_at": "2026-05-24T08:42:11Z"
                    }
                  },
                  "Business session imported": {
                    "summary": "Session KYB clonée (tronquée — payload de décision KYB V3 complet en réalité)",
                    "value": {
                      "session_id": "22222222-3333-4444-5555-666666666666",
                      "session_kind": "business",
                      "shared_from_session": "88888888-7777-6666-5555-444444444444",
                      "session_number": 982,
                      "session_url": null,
                      "status": "Approved",
                      "workflow_id": "9f9b1234-aaaa-bbbb-cccc-1234567890ab",
                      "vendor_data": "company-1"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation (token invalide, expiré, mauvaise cible ou référence à une session qui n'existe plus).",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Share Token": {
                    "summary": "JWT non valide",
                    "value": {
                      "share_token": [
                        "Invalid share token."
                      ]
                    }
                  },
                  "Expired Share Token": {
                    "summary": "Token ayant dépassé `exp`",
                    "value": {
                      "share_token": [
                        "Share token has expired."
                      ]
                    }
                  },
                  "Wrong audience": {
                    "summary": "Token non lié à cette application",
                    "value": {
                      "share_token": [
                        "This token is not valid for this application."
                      ]
                    }
                  },
                  "Original missing": {
                    "summary": "La session source a été supprimée",
                    "value": {
                      "share_token": [
                        "Original session does not exist."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante (une clé erronée, révoquée ou expirée renvoie `401`), ou cette session source a déjà été importée dans l'application appelante (une seule utilisation par récepteur).",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "summary": "Interdit",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Already imported": {
                    "summary": "Source déjà importée une fois",
                    "value": {
                      "detail": "This session has already been shared with your application."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`workflow_id` n'appartient pas à l'application appelante.",
            "content": {
              "application/json": {
                "examples": {
                  "Workflow not found": {
                    "summary": "Workflow inconnu",
                    "value": {
                      "detail": "Workflow does not exist for this application."
                    }
                  }
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "share_token",
                  "trust_review",
                  "workflow_id"
                ],
                "properties": {
                  "share_token": {
                    "type": "string",
                    "description": "Token de partage JWT délivré par [`POST /v3/session/{sessionId}/share/`](/sessions-api/share-session).",
                    "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                  },
                  "trust_review": {
                    "type": "boolean",
                    "description": "Si `true`, la session clonée conserve le `status` final de la source. Si `false`, elle est forcée à `In Review`.",
                    "example": false
                  },
                  "workflow_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID d'un workflow dans l'application appelante. Les identifiants inter-applications sont rejetés avec `404`.",
                    "example": "9f9b1234-aaaa-bbbb-cccc-1234567890ab"
                  },
                  "vendor_data": {
                    "type": "string",
                    "nullable": true,
                    "description": "Remplacement optionnel pour le `vendor_data` de la session clonée.",
                    "example": "user-1"
                  }
                }
              },
              "example": {
                "share_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                "trust_review": false,
                "workflow_id": "9f9b1234-aaaa-bbbb-cccc-1234567890ab",
                "vendor_data": "user-1"
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST \\\n  https://verification.didit.me/v3/session/import-shared/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"share_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n    \"trust_review\": false,\n    \"workflow_id\": \"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n    \"vendor_data\": \"user-1\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.import_shared(\n    share_token=\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n    trust_review=False,\n    workflow_id=\"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n    vendor_data=\"user-1\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.importShared({\n  share_token: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n  trust_review: false,\n  workflow_id: \"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n  vendor_data: \"user-1\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.ImportShared(ctx, didit.SessionsImportSharedParams{\n\tShareToken:  \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n\tTrustReview: false,\n\tWorkflowID:  \"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n\tVendorData:  didit.String(\"user-1\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsImportSharedParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().importShared(SessionsImportSharedParams.builder()\n        .shareToken(\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\")\n        .trustReview(false)\n        .workflowId(\"9f9b1234-aaaa-bbbb-cccc-1234567890ab\")\n        .vendorData(\"user-1\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->importShared([\n    'share_token' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',\n    'trust_review' => false,\n    'workflow_id' => '9f9b1234-aaaa-bbbb-cccc-1234567890ab',\n    'vendor_data' => 'user-1',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.import_shared(\n  share_token: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n  trust_review: false,\n  workflow_id: \"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n  vendor_data: \"user-1\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.ImportSharedAsync(new SessionsImportSharedParams\n{\n    ShareToken = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n    TrustReview = false,\n    WorkflowId = \"9f9b1234-aaaa-bbbb-cccc-1234567890ab\",\n    VendorData = \"user-1\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/kyb/search/": {
      "post": {
        "summary": "Recherche d'entreprise au registre KYB (autonome)",
        "operationId": "post_v3_kyb_search",
        "x-didit-sdk": {
          "resource": "kyb",
          "method": "search",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "description": "Recherchez des entreprises candidates dans les registres des sociétés officiels par nom et/ou numéro d'immatriculation. Il s'agit de l'étape 1 du flux de registre en deux étapes : **search** renvoie des candidats avec des informations succinctes, puis `POST /v3/kyb/select/` récupère le profil complet d'un candidat.\n\n**Facturation de la recherche.** Les recherches réussies utilisant une source payante de données d'entreprise coûtent USD 0.50 par requête, quel que soit le nombre de candidats. Les résultats vides, les échecs et les résultats fournis uniquement par d'autres sources ne sont pas facturés. Le prix applicable est réservé avant la recherche ; un solde insuffisant renvoie une erreur 403 avec le code `insufficient_credits`. Les tarifs contractuels s'appliquent lorsqu'ils ont été convenus, et un tarif de recherche contractuel non configuré renvoie une erreur 403. Les recherches en sandbox sont gratuites. Répéter une recherche réussie peut entraîner une nouvelle facturation ; la livraison du rappel n'ajoute pas de frais. La récupération du profil est facturée séparément. Ces frais de recherche s'appliquent également à la v2. Les candidats sont toujours renvoyés avec `fetch_status: \"pending\"` : les données complètes de l'entreprise ne sont récupérées (et facturées) qu'à la sélection.\n\n**`kyb_response_id` est éphémère.** Il s'agit d'un identifiant propre à chaque recherche, et non d'un identifiant d'entreprise stable. Sélectionnez rapidement après la recherche et relancez une recherche pour obtenir un nouvel identifiant au lieu de le stocker.\n\n**`tier` sélectionne la chaîne de fournisseurs.** `tier` indique le niveau de registre sur lequel s'exécute la recherche : `basic` (par défaut, la chaîne Lite), `shareholders` ou `ubo`. La recherche utilise la chaîne de fournisseurs qui dessert ce niveau, et il ne s'agit pas toujours de la même chaîne que celle consultée par la recherche Lite ; une recherche Lite vide ne prouve donc pas que le registre ne contient pas l'entreprise — effectuez une nouvelle recherche au niveau dont vous avez besoin. Un pays qui ne propose pas le niveau que vous indiquez fait l'objet d'une recherche au niveau le plus élevé qu'il propose, sans dépasser celui demandé. Récupérez le candidat depuis l'endpoint qui fournit ce niveau : `POST /v3/kyb/select/` (Lite), `POST /v3/kyb/shareholders/` ou `POST /v3/kyb/ubo/`.\n\n**Authentification.** `POST /v3/kyb/search/` (et `/v2/`) prend la clé API de votre application dans l'en-tête `x-api-key`. L'endpoint hébergé `POST /v1/kyb/search/` est la route authentifiée par session qu'appelle un flux de vérification hébergé : il répond `403` à une clé API et ne prend aucun `tier` — la configuration du registre KYB du workflow sélectionne la chaîne.\n\n**Deux modes.**\n- *Synchrone (par défaut) :* l'API interroge le registre jusqu'à ce que la recherche aboutisse et renvoie la liste finale des candidats (`search_resolved: true`).\n- *Asynchrone :* transmettez `webhook_url` et l'API répond immédiatement — généralement avec `search_status: \"pending\"` et une liste de candidats vide — puis envoie un rappel `kyb.registry_search.resolved` en POST à votre URL lorsque le registre a terminé. Le corps du rappel est `{\"event_id\", \"event_type\": \"kyb.registry_search.resolved\", \"request_id\", \"vendor_data\", \"metadata\", \"search_status\", \"search_resolved\", \"kyb_registry\", \"timestamp\", \"created_at\"}` — notez que `timestamp` et `created_at` dans le rappel sont des entiers epoch, contrairement au champ ISO `created_at` de cet endpoint — et est envoyé **non signé** (en-tête `X-Didit-Unsigned-Callback: true`, aucun `X-Signature`).\n\n**Codes de pays.** ISO 3166-1 alpha-2 (`GB`, `DE`), ainsi que les codes de subdivision `XX-YY` lorsque les registres sont régionaux — par exemple `US-CA` pour la Californie.\n\n**Sandbox.** Les clés des applications sandbox renvoient un candidat statique sans contacter aucun registre.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "country_code"
                ],
                "properties": {
                  "country_code": {
                    "type": "string",
                    "maxLength": 10,
                    "description": "Code ISO 3166-1 alpha-2 du pays dont le registre des sociétés doit être interrogé. Par exemple, `GB`. Lorsque les registres des sociétés fonctionnent au niveau de l'État ou de la province, ajoutez le code de subdivision ISO 3166-2 sous la forme `XX-YY` : `US-CA` effectue la recherche dans le registre de Californie. Les recherches aux États-Unis requièrent toujours la subdivision — un code `US` seul est rejeté. Insensible à la casse ; normalisé en majuscules.",
                    "example": "GB"
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom de l'entreprise à rechercher. `name` ou `registration_number` est requis.",
                    "example": "Tesco"
                  },
                  "registration_number": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Numéro d'immatriculation au registre à rechercher. `name` ou `registration_number` est requis."
                  },
                  "tier": {
                    "type": "string",
                    "enum": [
                      "basic",
                      "shareholders",
                      "ubo"
                    ],
                    "default": "basic",
                    "description": "Niveau de registre dont la chaîne de fournisseurs est utilisée pour cette recherche. `basic` (par défaut) effectue la recherche sur la chaîne Lite du pays ; `shareholders` et `ubo` effectuent la recherche sur la chaîne d'actionnariat de ce niveau, qui peut provenir d'une source différente, de sorte qu'une recherche Lite vide ne prouve pas que l'entreprise est absente du registre. Pour un pays qui ne propose pas le niveau spécifié, la recherche s'effectue au niveau le plus élevé proposé jusqu'à celui-ci. Récupérez le candidat à partir de l'endpoint qui fournit le niveau recherché : `POST /v3/kyb/select/` (Lite), `POST /v3/kyb/shareholders/` ou `POST /v3/kyb/ubo/`.",
                    "example": "basic"
                  },
                  "search_type": {
                    "type": "string",
                    "enum": [
                      "contains"
                    ],
                    "default": "contains",
                    "description": "Stratégie de correspondance des noms appliquée par la recherche dans le registre. `contains` est la seule valeur acceptée : aucune source de registre derrière la recherche ne propose de mode préfixe ou flou, `start_with` et `fuzzy` sont donc rejetés avec `400` (`not a valid choice`)."
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Votre identifiant pour cette recherche ; renvoyé en écho et inclus dans le rappel de webhook."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "JSON libre ; renvoyé en écho et inclus dans le callback du webhook."
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 500,
                    "description": "Bascule la recherche en mode asynchrone : l'API répond immédiatement et envoie un rappel POST non signé `kyb.registry_search.resolved` à cette URL lorsque la liste des candidats est prête."
                  }
                }
              },
              "example": {
                "country_code": "GB",
                "name": "Tesco",
                "search_type": "contains",
                "vendor_data": "company-1234"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/kyb/search/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"country_code\": \"GB\",\n    \"name\": \"Tesco\",\n    \"search_type\": \"contains\",\n    \"vendor_data\": \"company-1234\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.kyb.search(\n    country_code=\"GB\",\n    name=\"Tesco\",\n    search_type=\"contains\",\n    vendor_data=\"company-1234\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.kyb.search({\n  country_code: \"GB\",\n  name: \"Tesco\",\n  search_type: \"contains\",\n  vendor_data: \"company-1234\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.KYB.Search(ctx, didit.KYBSearchParams{\n\tCountryCode: \"GB\",\n\tName:        didit.String(\"Tesco\"),\n\tSearchType:  didit.Some(didit.KYBSearchParamsSearchType(\"contains\")),\n\tVendorData:  didit.String(\"company-1234\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.KybSearchParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.kyb().search(KybSearchParams.builder()\n        .countryCode(\"GB\")\n        .name(\"Tesco\")\n        .searchType(KybSearchParams.SearchType.of(\"contains\"))\n        .vendorData(\"company-1234\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->kyb->search([\n    'country_code' => 'GB',\n    'name' => 'Tesco',\n    'search_type' => 'contains',\n    'vendor_data' => 'company-1234',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.kyb.search(\n  country_code: \"GB\",\n  name: \"Tesco\",\n  search_type: \"contains\",\n  vendor_data: \"company-1234\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Kyb.SearchAsync(new KybSearchParams\n{\n    CountryCode = \"GB\",\n    Name = \"Tesco\",\n    SearchType = new KybSearchParamsSearchType(\"contains\"),\n    VendorData = \"company-1234\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Recherche acceptée. Le mode synchrone renvoie la liste des candidats résolus ; le mode webhook renvoie immédiatement (souvent `search_status: \"pending\"`) et délivre la liste finale via le callback `kyb.registry_search.resolved`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Avec `webhook_url` : l'identifiant de requête de recherche persistant, renvoyé sous la forme `request_id` dans le rappel `kyb.registry_search.resolved`. Sans `webhook_url` : un UUID de corrélation éphémère (la recherche n'est pas stockée)."
                    },
                    "kyb_registry": {
                      "$ref": "#/components/schemas/KYBRegistrySearchResults"
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Valeur renvoyée de `vendor_data` que vous avez envoyé."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "description": "Écho des `metadata` que vous avez envoyées."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "Resolved search": {
                    "summary": "Mode synchrone — liste finale des candidats",
                    "value": {
                      "request_id": "0c7e9a40-3a13-4f7e-8a44-9d2e2f1c5b6a",
                      "kyb_registry": {
                        "companies": [
                          {
                            "kyb_response_id": "69aeeb95febb0f1704042259",
                            "name": "Tesco PLC",
                            "registration_number": "00445790",
                            "status": "active",
                            "type": "Public Limited Company",
                            "risk_level": null,
                            "fetch_status": "pending"
                          },
                          {
                            "kyb_response_id": "69aeeb95febb0f170404225a",
                            "name": "E-TESCO LTD",
                            "registration_number": "15168476",
                            "status": "active",
                            "type": "Private Limited Company",
                            "risk_level": null,
                            "fetch_status": "pending"
                          }
                        ],
                        "pagination": {
                          "total": 2,
                          "page": 1,
                          "per_page": 25
                        },
                        "search_status": "resolved",
                        "search_resolved": true
                      },
                      "vendor_data": "company-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:40:00.000000+00:00"
                    }
                  },
                  "Pending search (webhook mode)": {
                    "summary": "`webhook_url` fournie — les candidats arrivent via le callback kyb.registry_search.resolved",
                    "value": {
                      "request_id": "5f2d8c1b-7e4a-4b9c-9f0d-3a6e8c2b1d4f",
                      "kyb_registry": {
                        "companies": [],
                        "pagination": {
                          "total": 0,
                          "page": 1,
                          "per_page": 25
                        },
                        "search_status": "pending",
                        "search_resolved": false
                      },
                      "vendor_data": "company-1234",
                      "metadata": {
                        "source": "onboarding"
                      },
                      "created_at": "2026-06-11T10:41:00.000000+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les problèmes au niveau des champs utilisent l'enveloppe standard de DRF ; la règle relative au nom/numéro d'immatriculation est signalée sous `non_field_errors`. Un pays non couvert par les registres renvoie `400` avec `code: kyb_registry_country_unsupported`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing search criteria": {
                    "summary": "Ni `name` ni `registration_number` n'ont été fournis",
                    "value": {
                      "non_field_errors": [
                        "Either 'name' or 'registration_number' is required."
                      ]
                    }
                  },
                  "Invalid country_code": {
                    "summary": "Doit être `XX` (alpha-2) ou une subdivision `XX-YY`",
                    "value": {
                      "country_code": [
                        "country_code must be a 2-letter ISO code."
                      ]
                    }
                  },
                  "Invalid search_type": {
                    "summary": "Seul `contains` est accepté",
                    "value": {
                      "search_type": [
                        "\"start_with\" is not a valid choice."
                      ]
                    }
                  },
                  "Invalid webhook_url": {
                    "summary": "`webhook_url` doit être une URL valide",
                    "value": {
                      "webhook_url": [
                        "Enter a valid URL."
                      ]
                    }
                  },
                  "Country not covered": {
                    "summary": "Aucun registre des sociétés ne couvre ce pays",
                    "value": {
                      "detail": "Company registry search is not available for this country. Enter the company details manually to continue.",
                      "code": "kyb_registry_country_unsupported"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Également renvoyé avant la recherche lorsque les frais de recherche applicables ne peuvent pas être couverts (`code: \"insufficient_credits\"`), ou lorsqu'un tarif de recherche contractuel est manquant.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée, ou quota de recherche épuisé. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements disposent d'un budget distinct de 600), avec les en-têtes `X-RateLimit-*` et `Retry-After`. Par ailleurs, les recherches payantes dans les registres sont limitées à 600 par application par heure : au-delà, la réponse est `429` avec `code: kyb_registry_search_limit_reached`, et les recherches traitées uniquement par des sources gratuites fonctionnent toujours. Attendez et relancez la recherche plus tard.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  },
                  "Search allowance spent": {
                    "summary": "Plus de 600 recherches payantes au cours de la dernière heure",
                    "value": {
                      "detail": "The maximum number of company registry searches for this session has been reached. Enter the company details manually to continue.",
                      "code": "kyb_registry_search_limit_reached"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Le fournisseur de registre KYB est temporairement indisponible : une réponse 5xx, un délai d'attente dépassé ou une erreur de connexion du registre en amont. La recherche n'est pas facturée. Réessayez plus tard, ou, dans le flux de vérification hébergé de Didit, l'utilisateur se voit automatiquement proposer la saisie manuelle de l'entreprise au lieu d'une erreur indiquant uniquement de réessayer.",
            "content": {
              "application/json": {
                "examples": {
                  "Registry provider outage": {
                    "summary": "Le fournisseur de registre n'a pas répondu à la recherche",
                    "value": {
                      "detail": "The KYB registry provider is temporarily unavailable. Please try again shortly.",
                      "code": "kyb_registry_provider_unavailable"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/kyb/select/": {
      "post": {
        "summary": "Sélection d'entreprise au registre KYB — niveau Lite (autonome)",
        "operationId": "post_v3_kyb_select",
        "x-didit-sdk": {
          "resource": "kyb",
          "method": "select",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "description": "Récupérer le profil de registre **Lite** d'un candidat renvoyé par `POST /v3/kyb/search/` — détails de l'entreprise, adresse enregistrée, identifiants, statut, activité et dirigeants, ainsi que le payload brut du registre. Les actionnaires et les bénéficiaires effectifs ultimes sont vendus via `POST /v3/kyb/shareholders/` et `POST /v3/kyb/ubo/`.\n\n**Association avec la recherche.** Transmettez le `kyb_response_id` du candidat exactement tel qu'il a été renvoyé par une recherche de la même application. Cet identifiant est éphémère et limité à cette recherche — sélectionnez-le rapidement, et effectuez une nouvelle recherche pour obtenir un nouvel identifiant plutôt que de le stocker.\n\n**Facturation.** Chaque sélection est facturée au tarif Lite du pays (les frais de recherche éventuels sont distincts) ; voir [Tarifs du registre KYB](/fr/getting-started/kyb-registry-pricing). Le solde est vérifié avant tout appel au registre (`403` en cas de solde insuffisant) et la facturation est enregistrée sur la session d'entreprise créée.\n\n**La persistance est obligatoire.** Chaque sélection crée une session d'entreprise (son identifiant est le `request_id`) afin que la facturation et la récupération puissent être suivies ; elle apparaît dans la console. `save_api_request` est accepté par souci de cohérence mais doit valoir `true` (valeur par défaut) — envoyer `false` renvoie `400`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KYBRegistryCandidateRequest"
              },
              "example": {
                "kyb_response_id": "69aeeb95febb0f1704042259",
                "vendor_data": "company-1234"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/kyb/select/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"kyb_response_id\": \"69aeeb95febb0f1704042259\",\n    \"vendor_data\": \"company-1234\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.kyb.select(\n    kyb_response_id=\"69aeeb95febb0f1704042259\",\n    vendor_data=\"company-1234\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.kyb.select({\n  kyb_response_id: \"69aeeb95febb0f1704042259\",\n  vendor_data: \"company-1234\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.KYB.Select(ctx, didit.KYBRegistryCandidateRequest{\n\tKYBResponseID: \"69aeeb95febb0f1704042259\",\n\tVendorData:    didit.String(\"company-1234\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.KYBRegistryCandidateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.kyb().select(KYBRegistryCandidateRequest.builder()\n        .kybResponseId(\"69aeeb95febb0f1704042259\")\n        .vendorData(\"company-1234\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->kyb->select([\n    'kyb_response_id' => '69aeeb95febb0f1704042259',\n    'vendor_data' => 'company-1234',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.kyb.select(\n  kyb_response_id: \"69aeeb95febb0f1704042259\",\n  vendor_data: \"company-1234\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Kyb.SelectAsync(new KYBRegistryCandidateRequest\n{\n    KybResponseId = \"69aeeb95febb0f1704042259\",\n    VendorData = \"company-1234\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Entreprise récupérée et facturée. `kyb_registry` contient le profil complet ; vérifiez `data_resolved` — lorsqu'il vaut `false`, le registre était encore en cours de traitement et l'enregistrement stocké se complète automatiquement une fois résolu.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de la session d'entreprise créée pour cette récupération. L'enregistrement stocké (visible dans la console) continue d'être mis à jour si la résolution du registre intervient après la réponse."
                    },
                    "registry_tier_requested": {
                      "type": "string",
                      "enum": [
                        "basic",
                        "shareholders",
                        "ubo"
                      ],
                      "description": "Le niveau proposé par cet endpoint : `basic` (Lite) pour select, `shareholders`, `ubo`."
                    },
                    "registry_tier_delivered": {
                      "type": "string",
                      "enum": [
                        "basic",
                        "shareholders",
                        "ubo"
                      ],
                      "description": "Le niveau réellement fourni et facturé. Inférieur à celui demandé lorsque les registres du pays ne contiennent aucune donnée d'actionnariat, ou que le registre n'a aucun enregistrement d'actionnariat pour cette entreprise."
                    },
                    "kyb_registry": {
                      "type": "object",
                      "description": "Profil complet de l'entreprise issu du registre.",
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Identifiant Didit pour cet enregistrement d'entreprise."
                        },
                        "node_id": {
                          "type": "string",
                          "example": "feature_kyb_registry"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "Not Finished",
                            "Approved",
                            "Declined",
                            "In Review"
                          ],
                          "description": "Évaluation par Didit de la vérification au registre (par exemple `In Review` lorsque l'entreprise n'est pas active dans le registre ou que les données d'actionnariat n'ont pas pu être dérivées)."
                        },
                        "registry_status": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "active",
                            "dissolved",
                            "deregistered",
                            "see full details",
                            "authorised",
                            "appointed representative",
                            "unauthorised",
                            "inactive",
                            "no longer authorised",
                            "closed",
                            "struck off"
                          ],
                          "description": "Statut normalisé de l'entreprise tel que déclaré par le registre."
                        },
                        "data_resolved": {
                          "type": "boolean",
                          "description": "`true` dès que le registre a renvoyé le profil complet. `false` lorsque le registre était toujours en cours de traitement après interrogation — l'enregistrement stocké se complète automatiquement dès que le registre a terminé."
                        },
                        "company_name": {
                          "type": "string",
                          "example": "Tesco PLC"
                        },
                        "registration_number": {
                          "type": "string",
                          "nullable": true,
                          "example": "00445790"
                        },
                        "country_code": {
                          "type": "string",
                          "description": "ISO 3166-1 alpha-2.",
                          "example": "GB"
                        },
                        "region": {
                          "type": "string",
                          "nullable": true,
                          "description": "Code de subdivision lorsque le registre est régional (par exemple `CA` pour `US-CA`) ; vide dans le cas contraire."
                        },
                        "company_type": {
                          "type": "string",
                          "nullable": true,
                          "example": "Public Limited Company"
                        },
                        "incorporation_date": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "example": "1947-11-27"
                        },
                        "registered_address": {
                          "type": "string",
                          "nullable": true,
                          "example": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA"
                        },
                        "tax_number": {
                          "type": "string",
                          "nullable": true,
                          "example": "GB412 8925 93"
                        },
                        "risk_level": {
                          "type": "string",
                          "nullable": true,
                          "description": "Niveau de risque indiqué par le registre, lorsqu'il est disponible."
                        },
                        "verification_status": {
                          "type": "string",
                          "enum": [
                            "verified",
                            "failed",
                            "unknown"
                          ],
                          "nullable": true,
                          "description": "Statut de vérification inter-juridictions : `verified` lorsque le statut au registre établit la régularité (`active`), `failed` lorsqu'il indique que l'entreprise n'est plus en activité (par exemple `dissolved`), sinon `unknown`. `null` pour une entreprise qui ne provient pas d'un registre et tant qu'une sélection est encore `pending`."
                        },
                        "is_from_registry": {
                          "type": "boolean",
                          "description": "Toujours `true` pour cet endpoint — le profil a été récupéré auprès d'un registre officiel."
                        },
                        "fetch_status": {
                          "type": "string",
                          "enum": [
                            "pending",
                            "resolved"
                          ],
                          "description": "Cycle de vie de la récupération auprès du registre. Reflété par `data_resolved`."
                        },
                        "alternative_names": {
                          "type": "string",
                          "nullable": true,
                          "description": "Dénominations commerciales, alternatives, anciennes ou dans la langue d'origine de l'entreprise sous forme de texte, lorsqu'elles sont déclarées."
                        },
                        "nature_of_business": {
                          "type": "string",
                          "nullable": true,
                          "description": "Description de l'activité ou code de classification, lorsqu'ils sont communiqués."
                        },
                        "registered_capital": {
                          "type": "string",
                          "nullable": true
                        },
                        "registered_capital_amount": {
                          "type": "string",
                          "nullable": true,
                          "description": "Montant décimal sous forme de chaîne, lorsqu'il est renseigné."
                        },
                        "registered_capital_currency": {
                          "type": "string",
                          "nullable": true,
                          "description": "Code ISO 4217, lorsqu'il est renseigné."
                        },
                        "website": {
                          "type": "string",
                          "nullable": true,
                          "example": "https://www.tesco.com/"
                        },
                        "email": {
                          "type": "string",
                          "nullable": true,
                          "example": "customer.service@tesco.co.uk"
                        },
                        "phone": {
                          "type": "string",
                          "nullable": true,
                          "example": "03301231688"
                        },
                        "legal_entity_identifier": {
                          "type": "string",
                          "nullable": true,
                          "description": "LEI, lorsqu'il est déclaré."
                        },
                        "location_of_registration": {
                          "type": "string",
                          "nullable": true,
                          "description": "Registre/juridiction auprès duquel l'entreprise est immatriculée, lorsqu'il est renseigné."
                        },
                        "vat_number": {
                          "type": "string",
                          "nullable": true,
                          "description": "Numéro de TVA de l'UE, lorsqu'il est recueilli lors de l'étape de registre hébergée ou modifié ultérieurement. Au moment de la sélection, il n'est généralement pas encore défini — la validation de la TVA et de l'identifiant fiscal s'exécute lorsque l'utilisateur final soumet l'étape de registre dans le flux hébergé."
                        },
                        "vat_validation_status": {
                          "type": "string",
                          "enum": [
                            "valid",
                            "invalid",
                            "format_valid",
                            "invalid_format",
                            "could_not_validate",
                            "not_applicable"
                          ],
                          "description": "Résultat de la validation du numéro de TVA ou, s'il n'y en a pas, du `tax_number`, lors de la soumission au registre. `valid` / `invalid` : déterminé par le registre officiel du pays (VIES UE, Norvège, Suisse, Brésil, Colombie, Costa Rica, Équateur, Paraguay ; Pologne également par son registre national de TVA). `format_valid` / `invalid_format` : déterminé par les règles de format et de chiffre de contrôle du pays lorsqu'aucun registre ne peut être interrogé. `could_not_validate` : le registre était indisponible. `not_applicable` : pas de numéro, un pays sans registre ni règles, ou une session sandbox."
                        },
                        "vat_validated_number": {
                          "type": "string",
                          "nullable": true,
                          "description": "Le numéro qui a été vérifié, tel que la source le connaît (par exemple le numéro de TVA dérivé d'un SIREN français ou d'un RSIN néerlandais). `null` si aucune vérification n'a été effectuée."
                        },
                        "vat_validation_source": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "eu_vies",
                            "pl_vat_white_list",
                            "no_brreg",
                            "ch_uid_register",
                            "br_receita_federal",
                            "co_rues",
                            "cr_hacienda",
                            "ec_sri",
                            "py_dnit",
                            "format_rules",
                            null
                          ],
                          "description": "La source ayant déterminé `vat_validation_status` : un registre officiel ou `format_rules`. Vaut `null` si aucune vérification n'a été exécutée."
                        },
                        "vat_validated_name": {
                          "type": "string",
                          "nullable": true,
                          "description": "Nom enregistré auprès de la source ayant validé le numéro, lorsqu'elle en communique un. Défini uniquement lorsque le statut est `valid`."
                        },
                        "vat_validated_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Adresse enregistrée auprès de la source ayant validé le numéro, lorsqu'elle en divulgue une. Renseigné uniquement lorsque le statut est `valid`."
                        },
                        "vat_checked_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Horodatage de la vérification. `null` si aucune vérification n'a été exécutée."
                        },
                        "financial_summary": {
                          "type": "object",
                          "nullable": true,
                          "description": "Détails sur les actions/le capital indiqués par le registre (devise, nombre total d'actions, catégories d'actions), lorsqu'ils sont disponibles."
                        },
                        "officers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "name": {
                                "type": "string",
                                "example": "MELISSA BETHELL"
                              },
                              "designation": {
                                "type": "string",
                                "nullable": true,
                                "description": "Désignation brute au registre (ex. `Director`, `Secretary`)."
                              },
                              "role": {
                                "type": "string",
                                "description": "Rôle normalisé dérivé de la désignation. Ensemble complet du modèle à 17 valeurs ; l'analyse du registre sur cet endpoint renvoie généralement director, non_executive_director, secretary, chairman ou company_officer.",
                                "enum": [
                                  "director",
                                  "non_executive_director",
                                  "secretary",
                                  "chairman",
                                  "ubo",
                                  "shareholder",
                                  "representative",
                                  "founder",
                                  "legal_advisor",
                                  "authorized_signatory",
                                  "trustee",
                                  "beneficiary",
                                  "company_officer",
                                  "settlor",
                                  "protector",
                                  "investor",
                                  "other"
                                ]
                              },
                              "nationality": {
                                "type": "string",
                                "nullable": true
                              },
                              "is_active": {
                                "type": "boolean",
                                "description": "`false` lorsque le registre indique que le titulaire du mandat a démissionné."
                              },
                              "kyc_status": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "Approved",
                                  "Declined",
                                  "Pending"
                                ],
                                "description": "Statut d'une session KYC associée, lorsqu'une session a été démarrée pour ce dirigeant. `null` sinon."
                              },
                              "kyc_session_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "URL de vérification de la session KYC associée, lorsqu'elle existe."
                              },
                              "first_name": {
                                "type": "string",
                                "nullable": true,
                                "description": "Prénom lorsqu'il est explicitement indiqué par le registre ; non déduit du nom complet."
                              },
                              "last_name": {
                                "type": "string",
                                "nullable": true,
                                "description": "Nom de famille lorsqu'il est explicitement indiqué par le registre."
                              },
                              "address": {
                                "type": "string",
                                "nullable": true,
                                "description": "Adresse du dirigeant indiquée par le registre."
                              },
                              "appointment_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date à laquelle le dirigeant a été nommé.",
                                "format": "date"
                              },
                              "termination_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de fin de mandat, lorsqu'elle est signalée.",
                                "format": "date"
                              },
                              "date_of_birth": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de naissance complète rapportée par le registre. Null lorsque seuls l'année ou le mois de naissance sont connus.",
                                "format": "date"
                              },
                              "date_of_birth_year": {
                                "type": "integer",
                                "nullable": true,
                                "minimum": 1,
                                "maximum": 9999,
                                "description": "Année de naissance indiquée par le registre, y compris lorsque la date complète n'est pas disponible."
                              },
                              "date_of_birth_month": {
                                "type": "integer",
                                "nullable": true,
                                "minimum": 1,
                                "maximum": 12,
                                "description": "Mois de naissance indiqué par le registre. Null lorsque seule l'année est connue."
                              }
                            }
                          },
                          "description": "Dirigeants, secrétaires et autres responsables extraits du registre."
                        },
                        "beneficial_owners": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "name": {
                                "type": "string"
                              },
                              "first_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "last_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "entity_type": {
                                "type": "string",
                                "enum": [
                                  "person",
                                  "company"
                                ],
                                "description": "Indique si le propriétaire est une personne physique ou une entité morale."
                              },
                              "roles": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Rôles normalisés (par exemple `ubo`, `shareholder`)."
                              },
                              "ownership_min_shares": {
                                "type": "string",
                                "nullable": true,
                                "description": "Limite inférieure de la fourchette d'actionnariat déclarée par le registre (par ex. `25%`)."
                              },
                              "ownership_max_shares": {
                                "type": "string",
                                "nullable": true,
                                "description": "Limite supérieure de la tranche d'actionnariat déclarée par le registre."
                              },
                              "is_active": {
                                "type": "boolean"
                              },
                              "kyc_status": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "Approved",
                                  "Declined",
                                  "Pending"
                                ]
                              },
                              "kyc_session_url": {
                                "type": "string",
                                "nullable": true
                              },
                              "effective_ownership_percent": {
                                "type": "number",
                                "nullable": true,
                                "description": "Pourcentage d'actionnariat analysé (borne maximale, ou à défaut borne minimale)."
                              },
                              "company_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "registration_number": {
                                "type": "string",
                                "nullable": true
                              },
                              "country_of_birth": {
                                "type": "string",
                                "nullable": true
                              },
                              "email": {
                                "type": "string",
                                "nullable": true
                              },
                              "nationality": {
                                "type": "string",
                                "nullable": true
                              },
                              "designation": {
                                "type": "string",
                                "nullable": true
                              },
                              "voting_min_shares": {
                                "type": "string",
                                "nullable": true
                              },
                              "voting_max_shares": {
                                "type": "string",
                                "nullable": true
                              },
                              "date_of_birth": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de naissance complète lorsqu'elle est rapportée.",
                                "format": "date"
                              },
                              "appointment_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de nomination lorsqu'elle est déclarée.",
                                "format": "date"
                              },
                              "shareholding": {
                                "$ref": "#/components/schemas/KYBRegistryShareholding"
                              }
                            }
                          },
                          "description": "Bénéficiaires effectifs / personnes exerçant un contrôle significatif extraits du registre. Peut être vide lorsque le registre ne divulgue pas l'actionnariat."
                        },
                        "addresses": {
                          "type": "array",
                          "nullable": true,
                          "description": "Chaque adresse indiquée par le registre, sous un format canonique unique. Nul lorsqu'il n'en indique aucune.",
                          "items": {
                            "$ref": "#/components/schemas/KYBRegistryAddress"
                          }
                        },
                        "industries": {
                          "type": "array",
                          "nullable": true,
                          "description": "Les activités dans lesquelles le registre classe l'entreprise, sous une forme canonique. Null lorsqu'il n'en indique aucune.",
                          "items": {
                            "$ref": "#/components/schemas/KYBRegistryIndustry"
                          }
                        },
                        "accounts": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true,
                          "description": "Dates de dépôt au registre, lorsqu'elles sont disponibles. Les déclarations annuelles et les assemblées générales utilisent last_annual_return_date et last_agm_date ; elles sont distinctes des comptes financiers."
                        },
                        "registry_data": {
                          "$ref": "#/components/schemas/KYBRegistryData"
                        },
                        "user_provided_data": {
                          "type": "object",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint (utilisé par le flux KYB hébergé lorsque les utilisateurs finaux modifient les données de registre)."
                        },
                        "confirmed_by_user_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint."
                        },
                        "last_console_edit_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Défini lorsqu'un réviseur de la console modifie l'enregistrement ultérieurement."
                        },
                        "is_editable": {
                          "type": "boolean",
                          "description": "Indique si les données issues du registre peuvent encore être modifiées dans le flux hébergé ou la console."
                        },
                        "registry_tier_delivered": {
                          "type": "string",
                          "enum": [
                            "basic",
                            "shareholders",
                            "ubo"
                          ],
                          "description": "Identique au `registry_tier_delivered` de premier niveau."
                        },
                        "registry_ownership_status": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "not_requested",
                            "delivered",
                            "not_held",
                            "unavailable"
                          ],
                          "description": "`delivered` lorsque les données d'actionnariat ont été reçues, `not_held` lorsque le registre d'actionnariat a répondu et ne répertorie pas cette entreprise (voir `registry_data.ownership_error`), `unavailable` lorsqu'un niveau d'actionnariat a été demandé mais que le registre n'en avait aucun pour cette entreprise ou n'a pas pu être interrogé (voir `registry_data.ownership_error`), `not_requested` pour le niveau Lite."
                        },
                        "ownership": {
                          "$ref": "#/components/schemas/KYBRegistryOwnership"
                        },
                        "registry_tier": {
                          "type": "string",
                          "nullable": true,
                          "description": "Le niveau de registre commandé par le workflow : `basic`, `shareholders` ou `ubo`. Également dans `ownership.tier_requested`."
                        },
                        "registry_monitoring": {
                          "type": "object",
                          "nullable": true,
                          "description": "Le moniteur de registre le plus récent pour l'entreprise, ou `null` s'il n'en existe aucun.",
                          "properties": {
                            "uuid": {
                              "type": "string",
                              "format": "uuid"
                            },
                            "status": {
                              "type": "string"
                            },
                            "unavailable_reason": {
                              "type": "string",
                              "nullable": true
                            },
                            "enrolled_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "cancelled_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "last_bill_date": {
                              "type": "string",
                              "format": "date",
                              "nullable": true
                            },
                            "next_bill_date": {
                              "type": "string",
                              "format": "date",
                              "nullable": true
                            },
                            "last_event_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "events_count": {
                              "type": "integer"
                            },
                            "watched_fields": {
                              "description": "Les champs de l'entreprise que le moniteur surveille."
                            }
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Valeur renvoyée de `vendor_data` que vous avez envoyé."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "description": "Écho des `metadata` que vous avez envoyées."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "Resolved company": {
                    "summary": "Profil complet du registre (liste des dirigeants tronquée par souci de concision)",
                    "value": {
                      "request_id": "9d4f2c7a-1b3e-4a5c-8d6f-0e9a8b7c6d5e",
                      "kyb_registry": {
                        "uuid": "f1e2d3c4-b5a6-4789-9c0d-1e2f3a4b5c6d",
                        "node_id": "feature_kyb_registry",
                        "status": "In Review",
                        "registry_status": "active",
                        "data_resolved": true,
                        "company_name": "Tesco PLC",
                        "registration_number": "00445790",
                        "country_code": "GB",
                        "region": "",
                        "company_type": "Public Limited Company",
                        "incorporation_date": "1947-11-27",
                        "registered_address": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA",
                        "tax_number": "GB412 8925 93",
                        "risk_level": "low risk",
                        "verification_status": "verified",
                        "is_from_registry": true,
                        "fetch_status": "resolved",
                        "alternative_names": "TESCO STORES (HOLDINGS) PUBLIC LIMITED COMPANY",
                        "nature_of_business": null,
                        "registered_capital": null,
                        "registered_capital_amount": null,
                        "registered_capital_currency": null,
                        "website": "https://www.tesco.com/",
                        "email": "customer.service@tesco.co.uk",
                        "phone": "03301231688",
                        "legal_entity_identifier": null,
                        "location_of_registration": null,
                        "financial_summary": {
                          "currency": "Pound (£)",
                          "total_number_of_shares": "8174378721",
                          "meta_detail": {
                            "Class_Of_Share": "Ordinary"
                          }
                        },
                        "officers": [
                          {
                            "uuid": "a1b2c3d4-e5f6-4789-9a0b-1c2d3e4f5a6b",
                            "name": "CHRISTOPHER JON TAYLOR",
                            "designation": "Secretary",
                            "role": "secretary",
                            "nationality": null,
                            "is_active": true,
                            "kyc_status": null,
                            "kyc_session_url": null
                          },
                          {
                            "uuid": "b2c3d4e5-f6a7-4890-8b1c-2d3e4f5a6b7c",
                            "name": "MELISSA BETHELL",
                            "designation": "Director",
                            "role": "director",
                            "nationality": "British",
                            "is_active": true,
                            "kyc_status": null,
                            "kyc_session_url": null
                          }
                        ],
                        "beneficial_owners": [],
                        "addresses": [
                          {
                            "address": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA",
                            "type": "legal_entity_registry_address",
                            "description": "registered office address"
                          }
                        ],
                        "industries": null,
                        "accounts": {
                          "last_account": "26 February 2025",
                          "next_account": "26 February 2026",
                          "due_by_date": "26 August 2026"
                        },
                        "registry_data": {},
                        "user_provided_data": null,
                        "confirmed_by_user_at": null,
                        "last_console_edit_at": null,
                        "is_editable": true
                      },
                      "vendor_data": "company-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:45:00.000000+00:00"
                    }
                  },
                  "Pending (registry still resolving)": {
                    "summary": "La sélection est restée en attente après l'interrogation — champs épars, auto-complétion côté serveur",
                    "value": {
                      "request_id": "9d4f2c7a-1b3e-4a5c-8d6f-0e9a8b7c6d5e",
                      "kyb_registry": {
                        "uuid": "7c0a4f7e-2b1d-4f6a-9c3e-8d5b2a1f0e9d",
                        "node_id": "feature_kyb_registry",
                        "status": "Not Finished",
                        "registry_status": null,
                        "data_resolved": false,
                        "company_name": "Tesco PLC",
                        "registration_number": "00445790",
                        "country_code": "GB",
                        "region": null,
                        "company_type": null,
                        "incorporation_date": null,
                        "registered_address": null,
                        "tax_number": null,
                        "risk_level": null,
                        "verification_status": null,
                        "is_from_registry": true,
                        "fetch_status": "pending",
                        "alternative_names": null,
                        "nature_of_business": null,
                        "registered_capital": null,
                        "registered_capital_amount": null,
                        "registered_capital_currency": null,
                        "website": null,
                        "email": null,
                        "phone": null,
                        "legal_entity_identifier": null,
                        "location_of_registration": null,
                        "financial_summary": {},
                        "officers": [],
                        "beneficial_owners": [],
                        "addresses": null,
                        "industries": null,
                        "accounts": null,
                        "registry_data": {},
                        "user_provided_data": null,
                        "confirmed_by_user_at": null,
                        "last_console_edit_at": null,
                        "is_editable": true
                      },
                      "vendor_data": "company-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:45:00.000000+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les problèmes au niveau des champs utilisent l'enveloppe standard de DRF. Un pays non couvert par les registres renvoie `400` avec `code: kyb_registry_country_unsupported`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing kyb_response_id": {
                    "summary": "`kyb_response_id` est requis",
                    "value": {
                      "kyb_response_id": [
                        "This field is required."
                      ]
                    }
                  },
                  "save_api_request=false rejected": {
                    "summary": "Les sélections sont toujours enregistrées",
                    "value": {
                      "save_api_request": [
                        "KYB registry select must be saved so billing and retrieval can be tracked."
                      ]
                    }
                  },
                  "Country not covered": {
                    "summary": "Aucun registre des sociétés ne couvre ce pays",
                    "value": {
                      "detail": "Company registry search is not available for this country. Enter the company details manually to continue.",
                      "code": "kyb_registry_country_unsupported"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout filtrage ou appel à un fournisseur.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/passive-liveness/": {
      "post": {
        "summary": "Détection passive du vivant",
        "description": "Détectez les attaques par présentation — photos imprimées, relectures sur écran, masques, deepfakes — à partir d'une seule image de visage. Aucune vidéo, aucun mouvement ni aucune interaction de l'utilisateur n'est requis.\n\n**Fonctionnement.** L'image est analysée par un modèle biométrique ; le visage détecté le plus grand est évalué et un `score` de vivacité (0–100) est calculé. Le `status` est `Declined` lorsqu'un avertissement de gravité `error` se déclenche :\n- `NO_FACE_DETECTED` — le modèle de vivacité n'a trouvé aucun visage,\n- `LOW_LIVENESS_SCORE` — score inférieur ou égal à `face_liveness_score_decline_threshold` (`30` par défaut),\n- `LIVENESS_FACE_ATTACK` — le modèle a détecté une attaque par présentation,\n- `FACE_IN_BLOCKLIST` / `POSSIBLE_FACE_IN_BLOCKLIST` — le visage correspond à une entrée de votre liste de blocage de visages.\n\n`MULTIPLE_FACES_DETECTED` est un signal de gravité `warning` (ne refuse pas), et `DUPLICATED_FACE` / `POSSIBLE_DUPLICATED_FACE` sont des signaux de gravité `information` indiquant que le même visage est déjà apparu dans une autre session approuvée (ils ne refusent jamais). `face_quality` et `face_luminance` (0–100, nullable) décrivent la qualité de capture.\n\n**Filtrage des doublons et de la liste de blocage.** S'exécute à **chaque** appel — avec ou sans `save_api_request` — en comparant le visage détecté à l'index de recherche faciale de votre application. Les visages antérieurs ayant le même `vendor_data` sont exclus de l'ensemble de la recherche d'index — ainsi, réexécuter la détection du vivant pour le même utilisateur ne déclenche pas `DUPLICATED_FACE`, et un visage placé sur liste de blocage provenant d'une session avec le propre `vendor_data` de l'appelant n'est PAS non plus signalé (le filtrage `FACE_IN_BLOCKLIST` est ignoré pour les visages ayant le même `vendor_data`).\n\n**Facturation.** Chaque réponse `200` consomme un crédit d'API Passive Liveness (déduit du crédit de votre forfait ou de votre solde de recharge). Un solde insuffisant renvoie `403` avant tout traitement d'image.\n\n**Persistance de session et enregistrement de visage (`save_api_request`, `true` par défaut).** Lorsqu'il est défini sur `true`, l'appel est conservé sous forme de session de type API (Business Console, `GET /v3/session/{sessionId}/decision/` via le `request_id` renvoyé, webhook `status.updated`), l'image de référence et le recadrage du visage sont stockés, et le visage détecté est **enregistré dans votre index de recherche faciale** afin que les futurs appels à la Recherche faciale et les vérifications de doublons puissent y correspondre. Lorsqu'il est défini sur `false`, l'appel est ponctuel : rien n'est stocké et le visage n'est pas enregistré (le filtrage de la liste de blocage et des doublons s'exécute toujours).\n\n**Sandbox.** Les clés API de sandbox ignorent tout traitement et facturation : après validation de la requête (une entrée mal formée renvoie toujours `400`), l'endpoint renvoie un payload fictif statique `Approved`, aucune session n'est conservée et aucun crédit n'est consommé.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou non valides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) — cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes/min par clé API sur l'ensemble des endpoints POST/PATCH/DELETE ; tout dépassement renvoie `429`.",
        "operationId": "post_v3passive-liveness",
        "x-didit-sdk": {
          "resource": "passive_liveness",
          "method": "check",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "user_image"
                ],
                "properties": {
                  "user_image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Image du visage de face (par exemple un selfie). Extensions autorisées : `tiff`, `jpg`, `jpeg`, `png`, `webp`. Taille maximale de téléversement : **5 MB** (les fichiers plus volumineux sont rejetés avec une erreur `400`). Les images sont automatiquement compressées à ~0.5 MB avant traitement, de sorte que les très hautes résolutions n'améliorent pas la précision. L'image doit contenir un seul sujet — lorsque plusieurs visages sont présents, le plus grand est évalué et un avertissement `MULTIPLE_FACES_DETECTED` est ajouté."
                  },
                  "face_liveness_score_decline_threshold": {
                    "type": "number",
                    "format": "float",
                    "default": 30,
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Seuil du score de détection du vivant (0–100). Un score calculé **inférieur ou égal** à cette valeur émet un avertissement `LOW_LIVENESS_SCORE` et définit `status` sur `Declined`. Valeur par défaut `30` ; augmentez-la pour une posture anti-usurpation plus stricte. Les valeurs en dehors de 0–100 renvoient `400`.",
                    "example": 30
                  },
                  "rotate_image": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lorsque la valeur est `true`, le service applique des rotations de 90 degrés à l'image fournie et utilise l'orientation qui produit la meilleure détection faciale. Utile lorsque l'orientation EXIF est manquante. Ajoute de la latence.",
                    "example": false
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Lorsque la valeur est `true` (par défaut), conserve l'appel sous forme de session de type API, stocke les images de visage, émet un webhook `status.updated` et enregistre le visage détecté dans votre index de recherche faciale. Lorsque la valeur est `false`, l'appel est ponctuel — rien n'est stocké et le visage n'est pas enregistré. Le filtrage par liste de blocage et la détection des doublons s'exécutent dans les deux cas.",
                    "example": true
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Identifiant opaque optionnel (votre identifiant d'utilisateur, e-mail, UUID…) stocké sur la session persistée et renvoyé. Également utilisé pour exclure les sessions antérieures avec le même `vendor_data` de la vérification de visage en double, afin que la revérification du même utilisateur ne déclenche pas `DUPLICATED_FACE`.",
                    "example": "user-123"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Objet JSON optionnel stocké avec la session (lorsque `save_api_request=true`) et renvoyé. Dans les requêtes multipart, envoyez-le sous forme de champ textuel encodé en JSON — il est analysé sous forme d'objet.",
                    "example": {
                      "flow": "withdrawal"
                    }
                  }
                }
              },
              "example": {
                "user_image": "(binary JPEG/PNG selfie)",
                "face_liveness_score_decline_threshold": 30,
                "rotate_image": false,
                "save_api_request": true,
                "vendor_data": "user-123",
                "metadata": {
                  "flow": "withdrawal"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Détection passive du vivant terminée. `liveness.score` est la confiance de 0 à 100 du modèle indiquant que l'image montre une personne vivante ; `status` est `Approved` sauf si un avertissement de gravité `error` a été déclenché. Un visage usurpé ou sur liste de blocage renvoie tout de même `200` — examinez `liveness.status` et `liveness.warnings`, et pas seulement le code HTTP. Lorsque `save_api_request=true`, `request_id` est l'identifiant de session conservé.",
            "content": {
              "application/json": {
                "examples": {
                  "Approved": {
                    "summary": "Visage vivant — aucun avertissement",
                    "value": {
                      "request_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
                      "liveness": {
                        "status": "Approved",
                        "method": "PASSIVE",
                        "score": 95.0,
                        "user_image": {
                          "entities": [
                            {
                              "bbox": [
                                661,
                                728,
                                1688,
                                2188
                              ],
                              "confidence": 0.732973,
                              "age": 26.91,
                              "gender": "male",
                              "race": null
                            }
                          ],
                          "best_angle": 0
                        },
                        "warnings": [],
                        "face_quality": 84.21,
                        "face_luminance": 50.33
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T01:04:42.763237+00:00"
                    }
                  },
                  "Declined - presentation attack": {
                    "summary": "Le modèle a signalé une usurpation (impression, rejeu, masque…)",
                    "value": {
                      "request_id": "f1c8c9b2-d3e4-4f5a-9b8c-7d6e5f4a3b2c",
                      "liveness": {
                        "status": "Declined",
                        "method": "PASSIVE",
                        "score": 12.5,
                        "user_image": {
                          "entities": [
                            {
                              "bbox": [
                                100,
                                120,
                                420,
                                540
                              ],
                              "confidence": 0.81,
                              "age": 30.1,
                              "gender": "female",
                              "race": null
                            }
                          ],
                          "best_angle": 0
                        },
                        "warnings": [
                          {
                            "risk": "LOW_LIVENESS_SCORE",
                            "feature": "LIVENESS",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Low liveness score",
                            "long_description": "The liveness check resulted in a low score, indicating potential use of non-live facial representations or poor-quality biometric data."
                          },
                          {
                            "risk": "LIVENESS_FACE_ATTACK",
                            "feature": "LIVENESS",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Liveness Face Attack",
                            "long_description": "The system detected a potential attempt to bypass the liveness check."
                          }
                        ],
                        "face_quality": 72.4,
                        "face_luminance": 48.2
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T01:04:42.763237+00:00"
                    }
                  },
                  "Declined - face on blocklist": {
                    "summary": "Visage vivant, mais il correspond à une entrée de liste de blocage",
                    "value": {
                      "request_id": "0b54a1de-22aa-4e0f-9c84-5a2b1f3c4d5e",
                      "liveness": {
                        "status": "Declined",
                        "method": "PASSIVE",
                        "score": 93.75,
                        "user_image": {
                          "entities": [
                            {
                              "bbox": [
                                40,
                                40,
                                100,
                                100
                              ],
                              "confidence": 0.722082,
                              "age": 27.0,
                              "gender": "male",
                              "race": null
                            }
                          ],
                          "best_angle": 0
                        },
                        "warnings": [
                          {
                            "risk": "FACE_IN_BLOCKLIST",
                            "feature": "LIVENESS",
                            "additional_data": {
                              "blocklisted_session_id": "882c42d5-8a4d-4d20-8080-a22f57822c86",
                              "blocklisted_session_number": 3242,
                              "api_service": null
                            },
                            "log_type": "error",
                            "short_description": "Face in blocklist",
                            "long_description": "The system identified a face in the blocklist, which means the face is not allowed to be verified."
                          }
                        ],
                        "face_quality": null,
                        "face_luminance": null
                      },
                      "vendor_data": "user-123",
                      "metadata": null,
                      "created_at": "2026-06-12T01:04:42.763237+00:00"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "liveness": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "Declined"
                          ],
                          "description": "`Declined` lorsqu'au moins un avertissement de gravité `error` s'est déclenché (aucun visage, score faible, attaque par présentation ou correspondance dans une liste de blocage) ; `Approved` dans les autres cas. Les entrées `warning`/`information` (visages multiples, doublons) n'entraînent jamais de refus à elles seules."
                        },
                        "method": {
                          "type": "string",
                          "enum": [
                            "PASSIVE"
                          ],
                          "description": "Toujours `PASSIVE` pour cet endpoint."
                        },
                        "score": {
                          "type": "number",
                          "format": "float",
                          "nullable": true,
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Confiance de détection du vivant (0–100, deux décimales) indiquant que l'image représente une personne vivante plutôt qu'une usurpation. `null` lorsque le modèle n'a renvoyé aucune confiance.",
                          "example": 95.0
                        },
                        "user_image": {
                          "type": "object",
                          "description": "Résultats de la détection faciale pour l'image soumise.",
                          "properties": {
                            "entities": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "bbox": {
                                    "type": "array",
                                    "items": {
                                      "type": "integer"
                                    },
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "description": "Boîte englobante du visage détecté sous forme de coordonnées en pixels `[x_min, y_min, x_max, y_max]` dans l'image traitée.",
                                    "example": [
                                      661,
                                      728,
                                      1688,
                                      2188
                                    ]
                                  },
                                  "confidence": {
                                    "type": "number",
                                    "format": "float",
                                    "minimum": 0,
                                    "maximum": 1,
                                    "description": "Indice de confiance de la détection faciale (0–1).",
                                    "example": 0.732973
                                  },
                                  "age": {
                                    "type": "number",
                                    "format": "float",
                                    "description": "Âge estimé par le modèle pour le visage détecté, en années. À titre informatif uniquement — n'affecte pas la décision de détection du vivant.",
                                    "example": 26.91
                                  },
                                  "gender": {
                                    "type": "string",
                                    "description": "Genre prédit par le modèle pour le visage détecté (`male` ou `female`). À titre informatif uniquement.",
                                    "example": "male"
                                  },
                                  "race": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "Champ réservé — toujours `null` dans les réponses de cet endpoint.",
                                    "example": null
                                  }
                                }
                              },
                              "description": "Une entrée par visage détecté. Le visage le plus grand est celui qui est évalué."
                            },
                            "best_angle": {
                              "type": "integer",
                              "nullable": true,
                              "description": "Rotation (en degrés) ayant produit la meilleure détection de visage ; non nulle uniquement lorsque `rotate_image=true` a corrigé l'orientation.",
                              "example": 0
                            }
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "description": "Signaux de risque. Gravité `error` (refus) : `NO_FACE_DETECTED`, `LOW_LIVENESS_SCORE` (score inférieur ou égal au seuil), `LIVENESS_FACE_ATTACK`, `FACE_IN_BLOCKLIST`, `POSSIBLE_FACE_IN_BLOCKLIST`. Gravité `warning` (examen, pas de refus) : `MULTIPLE_FACES_DETECTED`. Gravité `information` (pas de refus) : `DUPLICATED_FACE`, `POSSIBLE_DUPLICATED_FACE` — le même visage est déjà apparu dans une autre session approuvée.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "risk": {
                                "type": "string",
                                "enum": [
                                  "NO_FACE_DETECTED",
                                  "LOW_LIVENESS_SCORE",
                                  "LIVENESS_FACE_ATTACK",
                                  "MULTIPLE_FACES_DETECTED",
                                  "FACE_IN_BLOCKLIST",
                                  "POSSIBLE_FACE_IN_BLOCKLIST",
                                  "DUPLICATED_FACE",
                                  "POSSIBLE_DUPLICATED_FACE"
                                ],
                                "description": "Code de risque lisible par machine."
                              },
                              "feature": {
                                "type": "string",
                                "enum": [
                                  "LIVENESS"
                                ],
                                "description": "Fonctionnalité ayant émis l'avertissement. Toujours `LIVENESS` sur cet endpoint."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "additionalProperties": true,
                                "description": "`null` pour la plupart des avertissements. Les correspondances avec la liste de blocage contiennent `{blocklisted_session_id, blocklisted_session_number, api_service}` ; les correspondances de doublons contiennent `{duplicated_session_id, duplicated_session_number, api_service}` qui pointent vers la session correspondante."
                              },
                              "log_type": {
                                "type": "string",
                                "enum": [
                                  "error",
                                  "warning",
                                  "information"
                                ],
                                "description": "Gravité. Les avertissements `error` font passer `status` à `Declined` ; les entrées `warning` et `information` sont indicatives et ne refusent jamais d'elles-mêmes."
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Résumé du risque en une ligne, lisible par l'utilisateur."
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication lisible par l'humain du risque."
                              }
                            }
                          }
                        },
                        "face_quality": {
                          "type": "number",
                          "format": "float",
                          "nullable": true,
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Score de qualité de capture du visage détecté, normalisé de 0 à 100. `null` lorsque le modèle n'a pas pu produire une valeur fiable.",
                          "example": 84.21
                        },
                        "face_luminance": {
                          "type": "number",
                          "format": "float",
                          "nullable": true,
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Luminosité du visage détecté, normalisée de 0 à 100. `null` lorsqu'elle n'est pas disponible.",
                          "example": 50.33
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Écho des `vendor_data` que vous avez envoyées, ou `null`."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Écho de l'objet `metadata` que vous avez envoyé, ou `null`."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Horodatage ISO 8601 (UTC) du moment où la réponse a été générée, ex. `2026-06-12T01:04:42.763237+00:00`."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Renvoyée lorsque `user_image` est manquant, dépasse 5 Mo, possède une extension non prise en charge, échoue au décodage de l'image côté serveur, ou lorsqu'une option est hors limites. Les erreurs de champ utilisent l'enveloppe `{field: [messages]}` de DRF ; les échecs de décodage d'image utilisent `{\"error\": ...}`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing image": {
                    "summary": "`user_image` non inclus dans les données de formulaire",
                    "value": {
                      "user_image": [
                        "No file was submitted."
                      ]
                    }
                  },
                  "Invalid image format": {
                    "summary": "Extension autorisée mais contenu d'image indécodable",
                    "value": {
                      "error": "Invalid user image format.",
                      "code": "invalid_image"
                    }
                  },
                  "Unsupported file extension": {
                    "summary": "Extension de fichier autre que tiff/jpg/jpeg/png/webp",
                    "value": {
                      "user_image": [
                        "File extension “txt” is not allowed. Allowed extensions are: tiff, jpg, jpeg, png, webp."
                      ]
                    }
                  },
                  "File too large": {
                    "summary": "Le téléversement dépasse la limite de 5 MB",
                    "value": {
                      "user_image": [
                        "File size should not exceed 5 MB"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout traitement d'image.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/passive-liveness/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'user_image=@./selfie.jpg' \\\n  -F 'face_liveness_score_decline_threshold=30' \\\n  -F 'save_api_request=true' \\\n  -F 'vendor_data=user-123'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.passive_liveness.check(\n    user_image=open(\"user_image.jpg\", \"rb\"),\n    face_liveness_score_decline_threshold=30.0,\n    rotate_image=False,\n    save_api_request=True,\n    vendor_data=\"user-123\",\n    metadata={\"flow\": \"withdrawal\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.passiveLiveness.check({\n  user_image: await fileFromPath(\"user_image.jpg\"),\n  face_liveness_score_decline_threshold: 30.0,\n  rotate_image: false,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"withdrawal\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.PassiveLiveness.Check(ctx, didit.PassiveLivenessCheckParams{\n\tUserImage:                         didit.FileFromPath(\"user_image.jpg\"),\n\tFaceLivenessScoreDeclineThreshold: didit.Float(30.0),\n\tRotateImage:                       didit.Bool(false),\n\tSaveAPIRequest:                    didit.Bool(true),\n\tVendorData:                        didit.String(\"user-123\"),\n\tMetadata:                          didit.Some(map[string]any{\"flow\": \"withdrawal\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.PassiveLivenessCheckParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.passiveLiveness().check(PassiveLivenessCheckParams.builder()\n        .userImage(Path.of(\"user_image.jpg\"))\n        .faceLivenessScoreDeclineThreshold(30.0)\n        .rotateImage(false)\n        .saveApiRequest(true)\n        .vendorData(\"user-123\")\n        .metadata(Map.of(\"flow\", \"withdrawal\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->passiveLiveness->check([\n    'user_image' => File::fromPath('user_image.jpg'),\n    'face_liveness_score_decline_threshold' => 30.0,\n    'rotate_image' => false,\n    'save_api_request' => true,\n    'vendor_data' => 'user-123',\n    'metadata' => ['flow' => 'withdrawal'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.passive_liveness.check(\n  user_image: Pathname(\"user_image.jpg\"),\n  face_liveness_score_decline_threshold: 30.0,\n  rotate_image: false,\n  save_api_request: true,\n  vendor_data: \"user-123\",\n  metadata: { flow: \"withdrawal\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.PassiveLiveness.CheckAsync(new PassiveLivenessCheckParams\n{\n    UserImage = FileUpload.FromPath(\"user_image.jpg\"),\n    FaceLivenessScoreDeclineThreshold = 30.0,\n    RotateImage = false,\n    SaveApiRequest = true,\n    VendorData = \"user-123\",\n    Metadata = new Dictionary<string, object> { [\"flow\"] = \"withdrawal\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/database-validation/": {
      "post": {
        "summary": "Validation en base de données (autonome)",
        "operationId": "post_v3database-validation",
        "x-didit-sdk": {
          "resource": "database_validation",
          "method": "validate",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "description": "Validez les données d'identité d'une personne auprès de sources gouvernementales et de registres officiels — CPF au Brésil, RENAPER en Argentine, registres DNI en Espagne et au Pérou, INE au Mexique, et 100+ autres services dans 60+ pays.\n\n**Sélection des services.** Chaque pays propose un ou plusieurs services du catalogue identifiés par un `service_id` (par exemple `bra_cpf`, `arg_renaper`, `pan_cedula_sib`). Spécifiez les services souhaités avec le tableau `services` — si vous l'omettez, exactement **un** service par défaut est exécuté (le service de production établi depuis le plus longtemps pour ce pays). L'envoi de `services` fait également passer la réponse au format étendu avec `services_used` et `match_score`. Découvrez les services, leurs champs requis et leurs prix via `GET /v1/organization/database-validation-countries/` (un endpoint du catalogue non documenté dans cette spécification) ou dans l'éditeur de workflow de la Business Console. Certains services sont signalés par `requires_consent=true` dans le catalogue et exigent `consent=true` ; d'autres nécessitent un onboarding pour votre organisation avant de pouvoir être appelés.\n\n**Champs d'entrée.** `identification_number` est un champ universel associé automatiquement au champ spécifique correspondant du pays (voir sa description). Les règles de format par pays sont appliquées avant tout appel à un fournisseur (par exemple, le CPF brésilien doit comporter exactement 11 chiffres) et les erreurs de format ne sont jamais facturées. Les services biométriques nécessitent le téléversement d'un `selfie` (multipart uniquement) ; le RENAPER argentin exige en outre `gender`.\n\n**Résultats.** Chaque service renvoie une structure de `validation` champ par champ ainsi qu'un `outcome_code` neutre vis-à-vis des fournisseurs (`MATCH`, `PARTIAL_MATCH`, `NO_MATCH`, `DOCUMENT_NOT_FOUND`, `INVALID_DOCUMENT_FORMAT`, `INVALID_INPUT`, `MINOR_BLOCKED`, `DECEASED`, `BIOMETRIC_NO_MATCH`, `BIOMETRIC_IMAGE_UNUSABLE`, `INCONCLUSIVE`, `DOCUMENT_SUPERSEDED`, `REGISTRY_UNAVAILABLE`, `REGISTRY_ERROR`). Notez les distinctions : `NO_MATCH` correspond à une discordance définitive, `INCONCLUSIVE` signifie que le registre n'a pu confirmer dans un sens ou dans l'autre (à examiner, sans refuser), et `BIOMETRIC_IMAGE_UNUSABLE` correspond à un problème technique de selfie (à reprendre), contrairement au résultat définitif `BIOMETRIC_NO_MATCH`. Le `match_type` global effectue une agrégation sur l'ensemble des services (au moins une correspondance totale → `full_match`, sinon au moins une correspondance partielle → `partial_match`, sinon `no_match`) et `no_match_action`/`partial_match_action` le traduisent en `status` final. `validation_type` est dérivé : `two_by_two` lorsque deux services distincts ou plus ont produit une correspondance totale (sur le numéro d'identification, sur les nom complet + date de naissance combinés, ou sur l'adresse sans contradiction), sinon `one_by_one`.\n\n**Persistance.** `save_api_request` est défini par défaut sur **true** : le résultat est stocké sous forme de session (`request_id` fonctionne avec `GET /v3/session/{sessionId}/decision/`), apparaît dans la console et déclenche un webhook `status.updated`. Il contrôle également le format de `validations` — des objets par service lorsqu'il est enregistré, une structure fusionnée `{field: match}` dans le cas contraire.\n\n**Facturation.** Par service : chaque service renvoyant un résultat facturable est débité à son propre prix du catalogue. Les services en échec ou ignorés ne sont pas facturés, et les requêtes rejetées avec un code `400` ne coûtent rien. La vérification préalable du solde couvre la somme des prix des services sélectionnés (`403` en cas de solde insuffisant).\n\n**Échecs.** Si aucun service sélectionné ne renvoie de résultat exploitable, l'API renvoie une erreur `400` avec `validation_errors` si chaque tentative non aboutie a explicitement refusé les données saisies (`provider_rejected_input`, `retryable: false`). Corrigez les données d'entrée avant de réessayer. Sinon, elle renvoie une erreur `502` avec `validation_errors` (`empty_provider_response`, `retryable: true`), y compris pour les cas mixtes de refus d'entrée et de tentatives de secours indisponibles ; rien n'est facturé (une session reste enregistrée avec le statut `Not Finished` lorsque `save_api_request=true`). Lorsque seuls certains services échouent, la réponse `200` contient leurs échecs dans `database_validation.errors`.\n\n**Sandbox.** Les clés des applications sandbox ignorent les appels aux registres ainsi que la facturation et renvoient une réponse statique `full_match` — le payload de sandbox inclut toujours `services_used` et `match_score: 100`, quelle que soit la manière dont `services` a été envoyé ; ne vérifiez donc pas l'activation conditionnelle du format étendu en production ni la fraction de 0.0–1.0 de `match_score` sur les réponses du sandbox.\n\nEnvoyez la requête sous forme de `application/json`, ou de `multipart/form-data` lors du téléversement d'un `selfie`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "issuing_state"
                ],
                "properties": {
                  "issuing_state": {
                    "type": "string",
                    "description": "Code pays ISO 3166-1 **alpha-3** du registre auprès duquel effectuer la validation (par exemple `BRA`, `ESP`, `COL`). Détermine les services disponibles. Les codes non pris en charge renvoient `400` avec la liste complète des options valides.",
                    "example": "BRA"
                  },
                  "services": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "`service_id` du catalogue à exécuter pour ce pays (par exemple `[\"bra_cpf\"]`). Accepte également une chaîne unique ou une chaîne séparée par des virgules/encodée en JSON. **S'il est omis ou vide, exactement un service par défaut est exécuté** — le service en production le plus anciennement établi pour le pays ; les services plus récents, biométriques et à l'usage doivent être nommés explicitement. Envoyer `services` fait basculer la réponse vers le format étendu (ajoute `services_used` et `match_score`). Chaque identifiant doit exister et être actif pour l'`issuing_state` ; les services nécessitant un onboarding renvoient `400` jusqu'à leur activation pour votre organisation. Découvrez les services disponibles par pays via `GET /v1/organization/database-validation-countries/` (un endpoint du catalogue non documenté dans cette spécification) ou dans l'éditeur de workflow de la Business Console.",
                    "example": [
                      "bra_cpf"
                    ]
                  },
                  "validation_type": {
                    "type": "string",
                    "deprecated": true,
                    "description": "OBSOLÈTE. Accepté pour des raisons de rétrocompatibilité mais ignoré — le champ `validation_type` de la réponse est désormais déterminé par le nombre de services ayant obtenu une correspondance complète. Utilisez `services` pour cibler des services spécifiques."
                  },
                  "consent": {
                    "type": "boolean",
                    "default": false,
                    "description": "Définir sur `true` lorsque l'utilisateur final a explicitement consenti aux services de validation sélectionnés. Requis pour les services marqués avec `requires_consent=true` dans le catalogue — sans lui, ces services renvoient une erreur `400` avec `services_requiring_consent`."
                  },
                  "identification_number": {
                    "type": "string",
                    "description": "Numéro d'identification universel — mappé automatiquement au champ propre au pays approprié, ce qui vous permet de l'utiliser à la place de `personal_number`/`tax_number`/`document_number` : ARG→document_number (DNI), BOL→document_number (CI), BRA→tax_number (CPF, 11 chiffres), CHL→personal_number (RUT), COL→personal_number (Cédula), CRI→personal_number (Cédula), DOM→personal_number (Cédula, 11 chiffres), ECU→personal_number (Cédula, 10 chiffres), ESP→personal_number (DNI/NIE), GTM→document_number (DPI), HND→document_number (DNI), MEX→personal_number (CURP, 18 caractères), PAN→personal_number (Cédula), PER→personal_number (DNI, 8 chiffres), PRY→document_number (CI), SLV→document_number (DUI), URY→personal_number (CI), VEN→document_number (Cédula). Il n'écrase jamais un champ propre au pays explicitement fourni."
                  },
                  "first_name": {
                    "type": "string",
                    "description": "Le prénom de l'individu. Requis par certains services/pays.",
                    "example": "John"
                  },
                  "last_name": {
                    "type": "string",
                    "description": "Le nom de famille de l'individu. Requis par certains services/pays.",
                    "example": "Doe"
                  },
                  "middle_name": {
                    "type": "string",
                    "description": "Deuxième prénom, utilisé par les services de certains pays (AUS, NZL, …)."
                  },
                  "full_name": {
                    "type": "string",
                    "description": "Nom complet — certains services l'acceptent à la place du prénom/nom (par ex. les services CHN, qui comparent le nom dans le système d'écriture natif)."
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "description": "Date de naissance, `YYYY-MM-DD`. Requise par de nombreux services.",
                    "example": "1980-01-01"
                  },
                  "personal_number": {
                    "type": "string",
                    "description": "Identifiant personnel unique émis par le gouvernement. Utilisé par : CHL (RUT), COL (Cédula), CRI, DOM, ECU, ESP (DNI/NIE), MEX (CURP), PAN (Cédula), PER (DNI), URY. Envisagez d'utiliser plutôt `identification_number`."
                  },
                  "tax_number": {
                    "type": "string",
                    "description": "Identifiant fiscal. Utilisé par : BRA (CPF, 11 chiffres). Envisagez d'utiliser `identification_number` à la place."
                  },
                  "document_number": {
                    "type": "string",
                    "description": "Numéro de document. Utilisé par : ARG (DNI), BOL (CI), GTM (DPI), HND (DNI), PRY (CI), SLV (DUI), VEN (Cédula). Envisagez d'utiliser `identification_number` à la place."
                  },
                  "document_type": {
                    "type": "string",
                    "enum": [
                      "P",
                      "DL",
                      "ID",
                      "RP",
                      "SSC",
                      "HIC",
                      "WP",
                      "TC",
                      "VISA",
                      "PSC",
                      "BC",
                      "OTHER"
                    ],
                    "description": "Type de document en cours de validation : `P` passeport, `DL` permis de conduire, `ID` pièce d'identité nationale, `RP` titre de séjour (plus `SSC`, `HIC`, `WP`, `TC`, `VISA`, `PSC`, `BC`, `OTHER`). Requis par certains services (ex. ESP)."
                  },
                  "expiration_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date d'expiration du document, `YYYY-MM-DD`. Requise pour la validation ESP (Espagne).",
                    "example": "2030-01-15"
                  },
                  "date_of_issue": {
                    "type": "string",
                    "format": "date",
                    "description": "Date de délivrance du document, `YYYY-MM-DD` (fecha de expedición). Requise pour la validation de la cédula COL (Colombie).",
                    "example": "2015-06-20"
                  },
                  "nationality": {
                    "type": "string",
                    "description": "Nationalité au format ISO 3166-1 alpha-3. Requise par certains services."
                  },
                  "gender": {
                    "type": "string",
                    "enum": [
                      "M",
                      "F",
                      "X"
                    ],
                    "description": "Genre : `M`, `F`, ou `X` (autre/inconnu). Requis pour la validation RENAPER de l'Argentine (`arg_renaper`)."
                  },
                  "address": {
                    "description": "Adresse résidentielle. Privilégiez l'objet structuré `{\"street_1\":\"123 Main St\",\"street_2\":\"Apt 4B\",\"city\":\"Springfield\",\"region\":\"IL\",\"postal_code\":\"62701\",\"country\":\"US\"}` ; une chaîne complète sur une seule ligne est toujours acceptée. Requis par les services de vérification d'adresse ; lorsqu'un service définit des exigences d'adresse, les éléments manquants renvoient `400` avec `address_fields_required_by`.",
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "street_1": {
                            "type": "string"
                          },
                          "street_2": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "region": {
                            "type": "string"
                          },
                          "postal_code": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          }
                        }
                      },
                      {
                        "type": "string",
                        "description": "Adresse complète sur une seule ligne (héritée)."
                      }
                    ]
                  },
                  "address_element_1": {
                    "type": "string",
                    "description": "Adresse postale comprenant le numéro et le type de voie. En cas d'omission, dérivée de `address`."
                  },
                  "address_element_2": {
                    "type": "string",
                    "description": "Appartement, unité, bâtiment, étage ou ligne d'adresse supplémentaire. À envoyer uniquement lorsque vous disposez explicitement de cette information."
                  },
                  "address_element_3": {
                    "type": "string",
                    "description": "Ville, banlieue, district, localité ou quartier. Si elle est omise, dérivée de `address`."
                  },
                  "address_element_4": {
                    "type": "string",
                    "description": "État, province, région ou ville. Si omis, dérivé de `address`."
                  },
                  "address_element_5": {
                    "type": "string",
                    "description": "Code postal. `postal_code` est accepté comme alias."
                  },
                  "postal_code": {
                    "type": "string",
                    "description": "Code postal pour les services basés sur l'adresse (alias de `address_element_5`)."
                  },
                  "driver_license_number": {
                    "type": "string",
                    "description": "Numéro de permis de conduire pour les services gouvernementaux de vérification de documents (AUS, NZL, IND)."
                  },
                  "driver_license_card_number": {
                    "type": "string",
                    "description": "Numéro de carte physique du permis de conduire, lorsqu'il est requis séparément du numéro de permis (AUS)."
                  },
                  "driver_license_state": {
                    "type": "string",
                    "description": "État ou territoire de délivrance du permis de conduire (AUS)."
                  },
                  "driver_license_version": {
                    "type": "string",
                    "description": "Code de version du permis de conduire (NZL)."
                  },
                  "passport_number": {
                    "type": "string",
                    "description": "Numéro de passeport pour les services gouvernementaux de vérification de passeport (AUS, NZL, IND, CHN)."
                  },
                  "passport_expiration_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date d'expiration du passeport, `YYYY-MM-DD`, pour les services de vérification de passeport."
                  },
                  "passport_file_number": {
                    "type": "string",
                    "description": "Numéro de dossier de passeport (IND)."
                  },
                  "passport_issue_country": {
                    "type": "string",
                    "description": "Pays de délivrance du passeport (ISO 3166-1 alpha-3) pour les services de vérification de passeport."
                  },
                  "medicare_card_number": {
                    "type": "string",
                    "description": "Numéro de carte Medicare (AUS)."
                  },
                  "immi_card_number": {
                    "type": "string",
                    "description": "Numéro de l'ImmiCard australienne."
                  },
                  "immi_card_expiry_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date d'expiration de l'ImmiCard australienne."
                  },
                  "citizenship_certificate_number": {
                    "type": "string",
                    "description": "Numéro de certificat de citoyenneté (AUS)."
                  },
                  "birth_registration_number": {
                    "type": "string",
                    "description": "Numéro d'enregistrement de l'acte de naissance (AUS)."
                  },
                  "birth_registration_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date d'enregistrement de l'acte de naissance (AUS)."
                  },
                  "birth_registration_state": {
                    "type": "string",
                    "description": "État d'enregistrement de l'acte de naissance (AUS)."
                  },
                  "marriage_certificate_number": {
                    "type": "string",
                    "description": "Numéro de certificat de mariage (AUS)."
                  },
                  "change_of_name_certificate_number": {
                    "type": "string",
                    "description": "Numéro de certificat de changement de nom (AUS)."
                  },
                  "first_partner_name": {
                    "type": "string",
                    "description": "Prénom du partenaire sur un acte de mariage (AUS)."
                  },
                  "last_partner_name": {
                    "type": "string",
                    "description": "Nom de famille du conjoint sur un certificat de mariage (AUS)."
                  },
                  "voter_id": {
                    "type": "string",
                    "description": "Numéro d'électeur (IND EPIC, IRL)."
                  },
                  "epic_card": {
                    "type": "string",
                    "description": "Numéro de carte d'électeur EPIC (Inde)."
                  },
                  "pan": {
                    "type": "string",
                    "description": "PAN (Permanent Account Number) pour l'Inde."
                  },
                  "national_id": {
                    "type": "string",
                    "description": "Numéro national d'identité (CHN, MYS, KEN, KHM, NGA, ZAF, …)."
                  },
                  "cic": {
                    "type": "string",
                    "description": "Código de Identificación de Credencial (CIC) INE/IFE mexicain, 9 chiffres. Utilisé par le service de validité de la carte MEX INE (`mex_ine_vigencia`)."
                  },
                  "identificador_ciudadano": {
                    "type": "string",
                    "description": "Identificador del Ciudadano INE mexicain (9 chiffres). Utilisé avec `cic` pour les modèles INE modernes (E/F/G/H) dans `mex_ine_vigencia`."
                  },
                  "ocr": {
                    "type": "string",
                    "description": "Numéro OCR INE mexicain (13 chiffres, au verso de la carte). Utilisé avec `cic` pour le modèle D dans `mex_ine_vigencia`."
                  },
                  "voter_number": {
                    "type": "string",
                    "description": "Clave de Elector INE mexicaine (18 caractères). Utilisée avec `emission_number` pour les anciens modèles IFE (A/B/C) dans `mex_ine_vigencia`."
                  },
                  "emission_number": {
                    "type": "string",
                    "description": "Número de Emisión INE mexicain. Utilisé avec `voter_number` pour les anciens modèles IFE (A/B/C) dans `mex_ine_vigencia`."
                  },
                  "bvn": {
                    "type": "string",
                    "description": "Numéro de vérification bancaire nigérian."
                  },
                  "bank_card_number": {
                    "type": "string",
                    "description": "Numéro de carte bancaire (vérification de carte bancaire CHN)."
                  },
                  "company_registration_number": {
                    "type": "string",
                    "description": "Numéro d'immatriculation de l'entreprise tel que délivré par le registre des sociétés : le CNPJ au Brésil (par ex. `11222333000181`), le numéro d'immatriculation en Afrique du Sud (par ex. `1936/007721/06`). Requis par les services de registre des sociétés et de dirigeants d'entreprise (`bra_company_registry`, `bra_company_directors`, `zaf_company_registry`, `zaf_company_directors`)."
                  },
                  "company_name": {
                    "type": "string",
                    "description": "Raison sociale enregistrée, recoupée avec l'entrée du registre. Facultatif pour `zaf_company_registry`."
                  },
                  "initials": {
                    "type": "string",
                    "description": "Les initiales de la personne telles qu'imprimées sur le document. Requises par `zaf_drivers_license` ; acceptées par `zaf_bank_account_holder`."
                  },
                  "licence_number": {
                    "type": "string",
                    "description": "Numéro de permis de conduire tel qu'imprimé sur la carte, pour `zaf_drivers_license`. Lorsqu'il est omis, `document_number` est utilisé."
                  },
                  "refugee_file_number": {
                    "type": "string",
                    "description": "Numéro de dossier de réfugié délivré par le Department of Home Affairs d'Afrique du Sud. Requis par `zaf_refugee`."
                  },
                  "bank_name": {
                    "type": "string",
                    "description": "Nom de la banque détenant le compte. Requis par `zaf_bank_account_holder`."
                  },
                  "bank_account_number": {
                    "type": "string",
                    "description": "Numéro de compte bancaire. Requis par `zaf_bank_account_holder` ; accepté par `zaf_fraud_prevention`."
                  },
                  "account_type": {
                    "type": "string",
                    "description": "Type de compte bancaire pour `zaf_bank_account_holder` : `current`, `savings`, `transmission`, `subscriptionShare` ou `notKnown`, insensible à la casse. Toute autre valeur renvoie `400`. Omettez-le si vous ne connaissez pas le type : la vérification croisée du type de compte est alors indiquée comme non confirmée."
                  },
                  "phone_number": {
                    "type": "string",
                    "description": "Numéro de téléphone mobile de contact, pour les services effectuant des vérifications croisées de joignabilité (`zaf_bank_account_holder`, `zaf_fraud_prevention`, `zaf_refugee`)."
                  },
                  "right_thumb": {
                    "type": "string",
                    "description": "Empreinte du pouce droit encodée en Base64 pour `zaf_dha_fingerprint_match`, avec `left_thumb` ou seule."
                  },
                  "left_thumb": {
                    "type": "string",
                    "description": "Empreinte du pouce gauche encodée en Base64 pour `zaf_dha_fingerprint_match`, avec `right_thumb` ou seule."
                  },
                  "score_level": {
                    "type": "integer",
                    "description": "Niveau de score biométrique minimum pour `zaf_criminal_face_screening`. La valeur par défaut est `3`."
                  },
                  "max_matches": {
                    "type": "integer",
                    "description": "Nombre maximal de correspondances candidates renvoyées par `zaf_criminal_face_screening`. Vaut par défaut `1`."
                  },
                  "vehicle_register_number": {
                    "type": "string",
                    "description": "Numéro d'immatriculation du véhicule. Requis, avec `vehicle_licence_plate` et `vin`, par `zaf_vehicle_ownership`."
                  },
                  "vehicle_licence_plate": {
                    "type": "string",
                    "description": "Numéro de plaque d'immatriculation du véhicule. Requis, avec `vehicle_register_number` et `vin`, par `zaf_vehicle_ownership`."
                  },
                  "vin": {
                    "type": "string",
                    "description": "Numéro d'identification du véhicule (VIN ou numéro de châssis). Requis, avec `vehicle_register_number` et `vehicle_licence_plate`, par `zaf_vehicle_ownership`."
                  },
                  "ssn": {
                    "type": "string",
                    "description": "Numéro de sécurité sociale (États-Unis)."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Numéro de téléphone pour les services de Vérification du téléphone."
                  },
                  "landline": {
                    "type": "string",
                    "description": "Numéro de ligne fixe pour les services de vérification de téléphone."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Adresse e-mail pour les services de vérification d'identité."
                  },
                  "country_of_residence": {
                    "type": "string",
                    "description": "Pays de résidence au format ISO 3166-1 alpha-2. Utilisé par les services mondiaux d'enrichissement d'identité (par ex. `glb_identity_enrichment`) pour cibler la recherche.",
                    "example": "US"
                  },
                  "partial_match_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action effectuée par un `partial_match` sur `database_validation.status`. Par défaut : `NO_ACTION` (le statut reste `Approved`, avec un avertissement)."
                  },
                  "no_match_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Action effectuée par un `no_match` sur `database_validation.status`. Par défaut : `DECLINE`."
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Conserver la validation en tant que session (visibilité dans la console, endpoint de décision, webhook `status.updated`). Modifie également le format de réponse de `validations` : des objets par service lorsque `true` (par défaut), une table de champs fusionnée lorsque `false`."
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Votre identifiant pour l'utilisateur validé ; renvoyé en écho et conservé avec la session."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "JSON libre stocké avec la requête et renvoyé en écho."
                  }
                }
              },
              "example": {
                "issuing_state": "BRA",
                "services": [
                  "bra_cpf"
                ],
                "identification_number": "12345678900",
                "first_name": "John",
                "last_name": "Doe",
                "date_of_birth": "1980-01-01",
                "vendor_data": "user-1234"
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "issuing_state"
                ],
                "properties": {
                  "issuing_state": {
                    "type": "string",
                    "description": "Code pays ISO 3166-1 **alpha-3** du registre auprès duquel effectuer la validation (par exemple `BRA`, `ESP`, `COL`). Détermine les services disponibles. Les codes non pris en charge renvoient `400` avec la liste complète des options valides.",
                    "example": "BRA"
                  },
                  "services": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "`service_id` du catalogue à exécuter pour ce pays (par exemple `[\"bra_cpf\"]`). Accepte également une chaîne unique ou une chaîne séparée par des virgules/encodée en JSON. **S'il est omis ou vide, exactement un service par défaut est exécuté** — le service en production le plus anciennement établi pour le pays ; les services plus récents, biométriques et à l'usage doivent être nommés explicitement. Envoyer `services` fait basculer la réponse vers le format étendu (ajoute `services_used` et `match_score`). Chaque identifiant doit exister et être actif pour l'`issuing_state` ; les services nécessitant un onboarding renvoient `400` jusqu'à leur activation pour votre organisation. Découvrez les services disponibles par pays via `GET /v1/organization/database-validation-countries/` (un endpoint du catalogue non documenté dans cette spécification) ou dans l'éditeur de workflow de la Business Console.",
                    "example": [
                      "bra_cpf"
                    ]
                  },
                  "validation_type": {
                    "type": "string",
                    "deprecated": true,
                    "description": "OBSOLÈTE. Accepté pour des raisons de rétrocompatibilité mais ignoré — le champ `validation_type` de la réponse est désormais déterminé par le nombre de services ayant obtenu une correspondance complète. Utilisez `services` pour cibler des services spécifiques."
                  },
                  "consent": {
                    "type": "boolean",
                    "default": false,
                    "description": "Définir sur `true` lorsque l'utilisateur final a explicitement consenti aux services de validation sélectionnés. Requis pour les services marqués avec `requires_consent=true` dans le catalogue — sans lui, ces services renvoient une erreur `400` avec `services_requiring_consent`."
                  },
                  "identification_number": {
                    "type": "string",
                    "description": "Numéro d'identification universel — mappé automatiquement au champ propre au pays approprié, ce qui vous permet de l'utiliser à la place de `personal_number`/`tax_number`/`document_number` : ARG→document_number (DNI), BOL→document_number (CI), BRA→tax_number (CPF, 11 chiffres), CHL→personal_number (RUT), COL→personal_number (Cédula), CRI→personal_number (Cédula), DOM→personal_number (Cédula, 11 chiffres), ECU→personal_number (Cédula, 10 chiffres), ESP→personal_number (DNI/NIE), GTM→document_number (DPI), HND→document_number (DNI), MEX→personal_number (CURP, 18 caractères), PAN→personal_number (Cédula), PER→personal_number (DNI, 8 chiffres), PRY→document_number (CI), SLV→document_number (DUI), URY→personal_number (CI), VEN→document_number (Cédula). Il n'écrase jamais un champ propre au pays explicitement fourni."
                  },
                  "first_name": {
                    "type": "string",
                    "description": "Le prénom de l'individu. Requis par certains services/pays.",
                    "example": "John"
                  },
                  "last_name": {
                    "type": "string",
                    "description": "Le nom de famille de l'individu. Requis par certains services/pays.",
                    "example": "Doe"
                  },
                  "middle_name": {
                    "type": "string",
                    "description": "Deuxième prénom, utilisé par les services de certains pays (AUS, NZL, …)."
                  },
                  "full_name": {
                    "type": "string",
                    "description": "Nom complet — certains services l'acceptent à la place du prénom/nom (par ex. les services CHN, qui comparent le nom dans le système d'écriture natif)."
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "description": "Date de naissance, `YYYY-MM-DD`. Requise par de nombreux services.",
                    "example": "1980-01-01"
                  },
                  "personal_number": {
                    "type": "string",
                    "description": "Identifiant personnel unique émis par le gouvernement. Utilisé par : CHL (RUT), COL (Cédula), CRI, DOM, ECU, ESP (DNI/NIE), MEX (CURP), PAN (Cédula), PER (DNI), URY. Envisagez d'utiliser plutôt `identification_number`."
                  },
                  "tax_number": {
                    "type": "string",
                    "description": "Identifiant fiscal. Utilisé par : BRA (CPF, 11 chiffres). Envisagez d'utiliser `identification_number` à la place."
                  },
                  "document_number": {
                    "type": "string",
                    "description": "Numéro de document. Utilisé par : ARG (DNI), BOL (CI), GTM (DPI), HND (DNI), PRY (CI), SLV (DUI), VEN (Cédula). Envisagez d'utiliser `identification_number` à la place."
                  },
                  "document_type": {
                    "type": "string",
                    "enum": [
                      "P",
                      "DL",
                      "ID",
                      "RP",
                      "SSC",
                      "HIC",
                      "WP",
                      "TC",
                      "VISA",
                      "PSC",
                      "BC",
                      "OTHER"
                    ],
                    "description": "Type de document en cours de validation : `P` passeport, `DL` permis de conduire, `ID` pièce d'identité nationale, `RP` titre de séjour (plus `SSC`, `HIC`, `WP`, `TC`, `VISA`, `PSC`, `BC`, `OTHER`). Requis par certains services (ex. ESP)."
                  },
                  "expiration_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date d'expiration du document, `YYYY-MM-DD`. Requise pour la validation ESP (Espagne).",
                    "example": "2030-01-15"
                  },
                  "date_of_issue": {
                    "type": "string",
                    "format": "date",
                    "description": "Date de délivrance du document, `YYYY-MM-DD` (fecha de expedición). Requise pour la validation de la cédula COL (Colombie).",
                    "example": "2015-06-20"
                  },
                  "nationality": {
                    "type": "string",
                    "description": "Nationalité au format ISO 3166-1 alpha-3. Requise par certains services."
                  },
                  "gender": {
                    "type": "string",
                    "enum": [
                      "M",
                      "F",
                      "X"
                    ],
                    "description": "Genre : `M`, `F`, ou `X` (autre/inconnu). Requis pour la validation RENAPER de l'Argentine (`arg_renaper`)."
                  },
                  "address": {
                    "description": "Adresse résidentielle. Privilégiez l'objet structuré `{\"street_1\":\"123 Main St\",\"street_2\":\"Apt 4B\",\"city\":\"Springfield\",\"region\":\"IL\",\"postal_code\":\"62701\",\"country\":\"US\"}` ; une chaîne complète sur une seule ligne est toujours acceptée. Requis par les services de vérification d'adresse ; lorsqu'un service définit des exigences d'adresse, les éléments manquants renvoient `400` avec `address_fields_required_by`.",
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "street_1": {
                            "type": "string"
                          },
                          "street_2": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "region": {
                            "type": "string"
                          },
                          "postal_code": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          }
                        }
                      },
                      {
                        "type": "string",
                        "description": "Adresse complète sur une seule ligne (héritée)."
                      }
                    ]
                  },
                  "address_element_1": {
                    "type": "string",
                    "description": "Adresse postale comprenant le numéro et le type de voie. En cas d'omission, dérivée de `address`."
                  },
                  "address_element_2": {
                    "type": "string",
                    "description": "Appartement, unité, bâtiment, étage ou ligne d'adresse supplémentaire. À envoyer uniquement lorsque vous disposez explicitement de cette information."
                  },
                  "address_element_3": {
                    "type": "string",
                    "description": "Ville, banlieue, district, localité ou quartier. Si elle est omise, dérivée de `address`."
                  },
                  "address_element_4": {
                    "type": "string",
                    "description": "État, province, région ou ville. Si omis, dérivé de `address`."
                  },
                  "address_element_5": {
                    "type": "string",
                    "description": "Code postal. `postal_code` est accepté comme alias."
                  },
                  "postal_code": {
                    "type": "string",
                    "description": "Code postal pour les services basés sur l'adresse (alias de `address_element_5`)."
                  },
                  "driver_license_number": {
                    "type": "string",
                    "description": "Numéro de permis de conduire pour les services gouvernementaux de vérification de documents (AUS, NZL, IND)."
                  },
                  "driver_license_card_number": {
                    "type": "string",
                    "description": "Numéro de carte physique du permis de conduire, lorsqu'il est requis séparément du numéro de permis (AUS)."
                  },
                  "driver_license_state": {
                    "type": "string",
                    "description": "État ou territoire de délivrance du permis de conduire (AUS)."
                  },
                  "driver_license_version": {
                    "type": "string",
                    "description": "Code de version du permis de conduire (NZL)."
                  },
                  "passport_number": {
                    "type": "string",
                    "description": "Numéro de passeport pour les services gouvernementaux de vérification de passeport (AUS, NZL, IND, CHN)."
                  },
                  "passport_expiration_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date d'expiration du passeport, `YYYY-MM-DD`, pour les services de vérification de passeport."
                  },
                  "passport_file_number": {
                    "type": "string",
                    "description": "Numéro de dossier de passeport (IND)."
                  },
                  "passport_issue_country": {
                    "type": "string",
                    "description": "Pays de délivrance du passeport (ISO 3166-1 alpha-3) pour les services de vérification de passeport."
                  },
                  "medicare_card_number": {
                    "type": "string",
                    "description": "Numéro de carte Medicare (AUS)."
                  },
                  "immi_card_number": {
                    "type": "string",
                    "description": "Numéro de l'ImmiCard australienne."
                  },
                  "immi_card_expiry_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date d'expiration de l'ImmiCard australienne."
                  },
                  "citizenship_certificate_number": {
                    "type": "string",
                    "description": "Numéro de certificat de citoyenneté (AUS)."
                  },
                  "birth_registration_number": {
                    "type": "string",
                    "description": "Numéro d'enregistrement de l'acte de naissance (AUS)."
                  },
                  "birth_registration_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date d'enregistrement de l'acte de naissance (AUS)."
                  },
                  "birth_registration_state": {
                    "type": "string",
                    "description": "État d'enregistrement de l'acte de naissance (AUS)."
                  },
                  "marriage_certificate_number": {
                    "type": "string",
                    "description": "Numéro de certificat de mariage (AUS)."
                  },
                  "change_of_name_certificate_number": {
                    "type": "string",
                    "description": "Numéro de certificat de changement de nom (AUS)."
                  },
                  "first_partner_name": {
                    "type": "string",
                    "description": "Prénom du partenaire sur un acte de mariage (AUS)."
                  },
                  "last_partner_name": {
                    "type": "string",
                    "description": "Nom de famille du conjoint sur un certificat de mariage (AUS)."
                  },
                  "voter_id": {
                    "type": "string",
                    "description": "Numéro d'électeur (IND EPIC, IRL)."
                  },
                  "epic_card": {
                    "type": "string",
                    "description": "Numéro de carte d'électeur EPIC (Inde)."
                  },
                  "pan": {
                    "type": "string",
                    "description": "PAN (Permanent Account Number) pour l'Inde."
                  },
                  "national_id": {
                    "type": "string",
                    "description": "Numéro national d'identité (CHN, MYS, KEN, KHM, NGA, ZAF, …)."
                  },
                  "cic": {
                    "type": "string",
                    "description": "Código de Identificación de Credencial (CIC) INE/IFE mexicain, 9 chiffres. Utilisé par le service de validité de la carte MEX INE (`mex_ine_vigencia`)."
                  },
                  "identificador_ciudadano": {
                    "type": "string",
                    "description": "Identificador del Ciudadano INE mexicain (9 chiffres). Utilisé avec `cic` pour les modèles INE modernes (E/F/G/H) dans `mex_ine_vigencia`."
                  },
                  "ocr": {
                    "type": "string",
                    "description": "Numéro OCR INE mexicain (13 chiffres, au verso de la carte). Utilisé avec `cic` pour le modèle D dans `mex_ine_vigencia`."
                  },
                  "voter_number": {
                    "type": "string",
                    "description": "Clave de Elector INE mexicaine (18 caractères). Utilisée avec `emission_number` pour les anciens modèles IFE (A/B/C) dans `mex_ine_vigencia`."
                  },
                  "emission_number": {
                    "type": "string",
                    "description": "Número de Emisión INE mexicain. Utilisé avec `voter_number` pour les anciens modèles IFE (A/B/C) dans `mex_ine_vigencia`."
                  },
                  "bvn": {
                    "type": "string",
                    "description": "Numéro de vérification bancaire nigérian."
                  },
                  "bank_card_number": {
                    "type": "string",
                    "description": "Numéro de carte bancaire (vérification de carte bancaire CHN)."
                  },
                  "company_registration_number": {
                    "type": "string",
                    "description": "Numéro d'immatriculation de l'entreprise tel que délivré par le registre des sociétés : le CNPJ au Brésil (par ex. `11222333000181`), le numéro d'immatriculation en Afrique du Sud (par ex. `1936/007721/06`). Requis par les services de registre des sociétés et de dirigeants d'entreprise (`bra_company_registry`, `bra_company_directors`, `zaf_company_registry`, `zaf_company_directors`)."
                  },
                  "company_name": {
                    "type": "string",
                    "description": "Raison sociale enregistrée, recoupée avec l'entrée du registre. Facultatif pour `zaf_company_registry`."
                  },
                  "initials": {
                    "type": "string",
                    "description": "Les initiales de la personne telles qu'imprimées sur le document. Requises par `zaf_drivers_license` ; acceptées par `zaf_bank_account_holder`."
                  },
                  "licence_number": {
                    "type": "string",
                    "description": "Numéro de permis de conduire tel qu'imprimé sur la carte, pour `zaf_drivers_license`. Lorsqu'il est omis, `document_number` est utilisé."
                  },
                  "refugee_file_number": {
                    "type": "string",
                    "description": "Numéro de dossier de réfugié délivré par le Department of Home Affairs d'Afrique du Sud. Requis par `zaf_refugee`."
                  },
                  "bank_name": {
                    "type": "string",
                    "description": "Nom de la banque détenant le compte. Requis par `zaf_bank_account_holder`."
                  },
                  "bank_account_number": {
                    "type": "string",
                    "description": "Numéro de compte bancaire. Requis par `zaf_bank_account_holder` ; accepté par `zaf_fraud_prevention`."
                  },
                  "account_type": {
                    "type": "string",
                    "description": "Type de compte bancaire pour `zaf_bank_account_holder` : `current`, `savings`, `transmission`, `subscriptionShare` ou `notKnown`, insensible à la casse. Toute autre valeur renvoie `400`. Omettez-le si vous ne connaissez pas le type : la vérification croisée du type de compte est alors indiquée comme non confirmée."
                  },
                  "phone_number": {
                    "type": "string",
                    "description": "Numéro de téléphone mobile de contact, pour les services effectuant des vérifications croisées de joignabilité (`zaf_bank_account_holder`, `zaf_fraud_prevention`, `zaf_refugee`)."
                  },
                  "right_thumb": {
                    "type": "string",
                    "description": "Empreinte du pouce droit encodée en Base64 pour `zaf_dha_fingerprint_match`, avec `left_thumb` ou seule."
                  },
                  "left_thumb": {
                    "type": "string",
                    "description": "Empreinte du pouce gauche encodée en Base64 pour `zaf_dha_fingerprint_match`, avec `right_thumb` ou seule."
                  },
                  "score_level": {
                    "type": "integer",
                    "description": "Niveau de score biométrique minimum pour `zaf_criminal_face_screening`. La valeur par défaut est `3`."
                  },
                  "max_matches": {
                    "type": "integer",
                    "description": "Nombre maximal de correspondances candidates renvoyées par `zaf_criminal_face_screening`. Vaut par défaut `1`."
                  },
                  "vehicle_register_number": {
                    "type": "string",
                    "description": "Numéro d'immatriculation du véhicule. Requis, avec `vehicle_licence_plate` et `vin`, par `zaf_vehicle_ownership`."
                  },
                  "vehicle_licence_plate": {
                    "type": "string",
                    "description": "Numéro de plaque d'immatriculation du véhicule. Requis, avec `vehicle_register_number` et `vin`, par `zaf_vehicle_ownership`."
                  },
                  "vin": {
                    "type": "string",
                    "description": "Numéro d'identification du véhicule (VIN ou numéro de châssis). Requis, avec `vehicle_register_number` et `vehicle_licence_plate`, par `zaf_vehicle_ownership`."
                  },
                  "ssn": {
                    "type": "string",
                    "description": "Numéro de sécurité sociale (États-Unis)."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Numéro de téléphone pour les services de Vérification du téléphone."
                  },
                  "landline": {
                    "type": "string",
                    "description": "Numéro de ligne fixe pour les services de vérification de téléphone."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Adresse e-mail pour les services de vérification d'identité."
                  },
                  "country_of_residence": {
                    "type": "string",
                    "description": "Pays de résidence au format ISO 3166-1 alpha-2. Utilisé par les services mondiaux d'enrichissement d'identité (par ex. `glb_identity_enrichment`) pour cibler la recherche.",
                    "example": "US"
                  },
                  "partial_match_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action effectuée par un `partial_match` sur `database_validation.status`. Par défaut : `NO_ACTION` (le statut reste `Approved`, avec un avertissement)."
                  },
                  "no_match_action": {
                    "type": "string",
                    "enum": [
                      "DECLINE",
                      "NO_ACTION"
                    ],
                    "default": "DECLINE",
                    "description": "Action effectuée par un `no_match` sur `database_validation.status`. Par défaut : `DECLINE`."
                  },
                  "save_api_request": {
                    "type": "boolean",
                    "default": true,
                    "description": "Conserver la validation en tant que session (visibilité dans la console, endpoint de décision, webhook `status.updated`). Modifie également le format de réponse de `validations` : des objets par service lorsque `true` (par défaut), une table de champs fusionnée lorsque `false`."
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Votre identifiant pour l'utilisateur validé ; renvoyé en écho et conservé avec la session."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "JSON libre stocké avec la requête et renvoyé en écho."
                  },
                  "selfie": {
                    "type": "string",
                    "format": "binary",
                    "description": "Image de selfie (`jpg`, `jpeg`, `png`, `webp` ; 2 Mo max — les images sont compressées à ~1.5 Mo avant le téléversement vers le registre) pour les services de validation biométrique, par exemple RENAPER en Argentine (`arg_renaper`) et SIB au Panama (`pan_cedula_sib`, `pan_cedula_sib_plus`). Requis dès lors qu'un service sélectionné l'indique comme champ obligatoire. Uniquement disponible via `multipart/form-data`."
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/database-validation/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"issuing_state\": \"BRA\",\n    \"services\": [\"bra_cpf\"],\n    \"identification_number\": \"12345678900\",\n    \"first_name\": \"John\",\n    \"last_name\": \"Doe\",\n    \"date_of_birth\": \"1980-01-01\",\n    \"vendor_data\": \"user-1234\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.database_validation.validate(\n    issuing_state=\"BRA\",\n    services=[\"bra_cpf\"],\n    identification_number=\"12345678900\",\n    first_name=\"John\",\n    last_name=\"Doe\",\n    date_of_birth=\"1980-01-01\",\n    vendor_data=\"user-1234\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.databaseValidation.validate({\n  issuing_state: \"BRA\",\n  services: [\"bra_cpf\"],\n  identification_number: \"12345678900\",\n  first_name: \"John\",\n  last_name: \"Doe\",\n  date_of_birth: \"1980-01-01\",\n  vendor_data: \"user-1234\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.DatabaseValidation.Validate(ctx, didit.DatabaseValidationValidateParams{\n\tIssuingState:         \"BRA\",\n\tServices:             didit.Some([]string{\"bra_cpf\"}),\n\tIdentificationNumber: didit.String(\"12345678900\"),\n\tFirstName:            didit.String(\"John\"),\n\tLastName:             didit.String(\"Doe\"),\n\tDateOfBirth:          didit.String(\"1980-01-01\"),\n\tVendorData:           didit.String(\"user-1234\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.LocalDate;\nimport java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.DatabaseValidationValidateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.databaseValidation().validate(DatabaseValidationValidateParams.builder()\n        .issuingState(\"BRA\")\n        .services(List.of(\"bra_cpf\"))\n        .identificationNumber(\"12345678900\")\n        .firstName(\"John\")\n        .lastName(\"Doe\")\n        .dateOfBirth(LocalDate.parse(\"1980-01-01\"))\n        .vendorData(\"user-1234\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->databaseValidation->validate([\n    'issuing_state' => 'BRA',\n    'services' => ['bra_cpf'],\n    'identification_number' => '12345678900',\n    'first_name' => 'John',\n    'last_name' => 'Doe',\n    'date_of_birth' => '1980-01-01',\n    'vendor_data' => 'user-1234',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.database_validation.validate(\n  issuing_state: \"BRA\",\n  services: [\"bra_cpf\"],\n  identification_number: \"12345678900\",\n  first_name: \"John\",\n  last_name: \"Doe\",\n  date_of_birth: \"1980-01-01\",\n  vendor_data: \"user-1234\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.DatabaseValidation.ValidateAsync(new DatabaseValidationValidateParams\n{\n    IssuingState = \"BRA\",\n    Services = new string[] { \"bra_cpf\" },\n    IdentificationNumber = \"12345678900\",\n    FirstName = \"John\",\n    LastName = \"Doe\",\n    DateOfBirth = \"1980-01-01\",\n    VendorData = \"user-1234\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Validation terminée — au moins un service sélectionné a renvoyé un résultat exploitable. Inspectez `database_validation.match_type` pour le résultat global, `validations` pour les comparaisons de champs par service et les `outcome_code`s, et `errors` (le cas échéant) pour les services en échec.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de session persistante lorsque `save_api_request=true` (utilisable avec `GET /v3/session/{sessionId}/decision/`) ; sinon un UUID de corrélation temporaire."
                    },
                    "database_validation": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "Approved",
                            "Declined",
                            "In Review"
                          ],
                          "description": "`Declined` lorsque le `match_type` global déclenche une action `DECLINE` (`no_match_action` est défini par défaut sur `DECLINE`, `partial_match_action` sur `NO_ACTION`) ; `In Review` lorsqu'aucun service n'a produit de comparaison exploitable, par exemple lorsque le seul service sélectionné a renvoyé `REGISTRY_UNAVAILABLE` ou `INCONCLUSIVE` ; `Approved` dans les autres cas. Une requête ayant sélectionné plusieurs services peut être `Approved` sur la correspondance d'un service alors qu'un autre était indisponible, vérifiez donc également `errors` et les `outcome_code`s de chaque service."
                        },
                        "issuing_state": {
                          "type": "string",
                          "description": "Écho du pays ISO 3166-1 alpha-3 par rapport auquel la validation a été effectuée.",
                          "example": "BRA"
                        },
                        "validation_type": {
                          "type": "string",
                          "enum": [
                            "one_by_one",
                            "two_by_two"
                          ],
                          "description": "Dérivé des résultats : `two_by_two` lorsque ≥ 2 services distincts ont produit une correspondance complète (sur le numéro d'identification, sur le nom complet et la date de naissance combinés, ou sur l'adresse sans contradiction) ; `one_by_one` dans le cas contraire. (Le champ de requête du même nom est obsolète et ignoré.)"
                        },
                        "screened_data": {
                          "type": "object",
                          "description": "Champs d'entrée renvoyés, tels qu'ils ont été envoyés aux services sélectionnés (dates normalisées au format `YYYY-MM-DD` ; un `selfie`, lorsqu'il est envoyé, est renvoyé sous la forme d'une URL pré-signée ; `consent_obtained: true` est ajouté lorsque le consentement a été donné)."
                        },
                        "match_type": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "full_match",
                            "partial_match",
                            "no_match"
                          ],
                          "description": "Résultat global agrégé à travers les services avec des comparaisons au niveau des champs : tout `full_match` → `full_match` ; sinon tout `partial_match` → `partial_match` ; sinon `no_match`. Les services sans comparaison détaillée (résultat uniquement), comme le filtrage biométrique des antécédents judiciaires, peuvent renvoyer `null` ; examinez chaque élément dans `validations` pour connaître son `outcome_code`."
                        },
                        "validations": {
                          "description": "La structure dépend de `save_api_request`. **`true` (par défaut) :** un tableau d'objets par service (`service_id`, `service_name`, `validation`, `outcome_code`, `outcome_detail`, `source_data`). **`false` :** un objet plat unique fusionnant les résultats au niveau des champs de tous les services (`{\"full_name\": \"full_match\", ...}`).",
                          "oneOf": [
                            {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "description": "Résultat de validation par service (renvoyé lorsque `save_api_request=true`, valeur par défaut).",
                                "properties": {
                                  "service_id": {
                                    "type": "string",
                                    "description": "Identifiant de catalogue du service ayant produit ce résultat (par exemple `bra_cpf`).",
                                    "example": "bra_cpf"
                                  },
                                  "service_name": {
                                    "type": "string",
                                    "description": "Nom de catalogue lisible par l'humain du service.",
                                    "example": "Brazil - CPF status check"
                                  },
                                  "validation": {
                                    "type": "object",
                                    "description": "Comparaison champ par champ entre votre entrée et l'enregistrement du registre. Les clés sont les noms canoniques des champs (`full_name`, `date_of_birth`, `identification_number`, `address`, …) ; les valeurs sont `full_match`, `partial_match` ou `no_match`.",
                                    "additionalProperties": {
                                      "type": "string",
                                      "enum": [
                                        "full_match",
                                        "partial_match",
                                        "no_match"
                                      ]
                                    }
                                  },
                                  "outcome_code": {
                                    "type": "string",
                                    "enum": [
                                      "MATCH",
                                      "PARTIAL_MATCH",
                                      "NO_MATCH",
                                      "DOCUMENT_NOT_FOUND",
                                      "INVALID_DOCUMENT_FORMAT",
                                      "INVALID_INPUT",
                                      "MINOR_BLOCKED",
                                      "DECEASED",
                                      "BIOMETRIC_NO_MATCH",
                                      "BIOMETRIC_IMAGE_UNUSABLE",
                                      "INCONCLUSIVE",
                                      "DOCUMENT_SUPERSEDED",
                                      "REGISTRY_UNAVAILABLE",
                                      "REGISTRY_ERROR"
                                    ],
                                    "description": "Résultat indépendant du fournisseur de la consultation du registre. `MATCH`/`PARTIAL_MATCH`/`NO_MATCH` décrivent la comparaison ; `DOCUMENT_NOT_FOUND` signifie que l'identifiant n'est pas dans le registre ; `INCONCLUSIVE` signifie que le registre n'a pu confirmer ni dans un sens ni dans l'autre (acheminé vers un examen — PAS une absence de correspondance) ; `BIOMETRIC_NO_MATCH` est une non-concordance faciale définitive tandis que `BIOMETRIC_IMAGE_UNUSABLE` est un problème technique d'image (reprendre le selfie) ; `DECEASED`/`MINOR_BLOCKED` sont des résultats liés aux politiques du registre ; `DOCUMENT_SUPERSEDED` signifie que l'identité correspond mais que l'édition du document présenté n'est pas celle enregistrée (une édition plus récente a été délivrée) ; `INVALID_DOCUMENT_FORMAT`/`INVALID_INPUT` signifient que le registre lui-même a rejeté les données qui lui ont été envoyées ; `REGISTRY_UNAVAILABLE`/`REGISTRY_ERROR` indiquent des défaillances en amont."
                                  },
                                  "outcome_detail": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "Détail brut du statut en amont étayant le code de résultat (ex. un code de statut HTTP ou du registre)."
                                  },
                                  "source_data": {
                                    "type": "object",
                                    "nullable": true,
                                    "description": "Vue nettoyée et normalisée de l'enregistrement du registre utilisant des noms de champs canoniques (`identification_number`, `first_name`, `last_name`, `date_of_birth`, ainsi que des indicateurs spécifiques au registre). Les champs d'image, lorsqu'ils sont présents, sont renvoyés sous forme d'URL pré-signées."
                                  }
                                }
                              }
                            },
                            {
                              "type": "object",
                              "additionalProperties": {
                                "type": "string",
                                "enum": [
                                  "full_match",
                                  "partial_match",
                                  "no_match"
                                ]
                              },
                              "description": "Résultats fusionnés au niveau des champs (format sans état `save_api_request=false`)."
                            }
                          ]
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "feature": {
                                "type": "string",
                                "description": "Fonctionnalité ayant émis l'avertissement."
                              },
                              "risk": {
                                "type": "string",
                                "description": "Identifiant de risque lisible par machine."
                              },
                              "additional_data": {
                                "type": "object",
                                "nullable": true,
                                "description": "Contexte supplémentaire pour l'avertissement, lorsqu'il est disponible."
                              },
                              "log_type": {
                                "type": "string",
                                "description": "`warning`, `information` ou `error` — manière dont le risque a affecté le résultat."
                              },
                              "short_description": {
                                "type": "string",
                                "description": "Résumé lisible par un humain sur une ligne."
                              },
                              "long_description": {
                                "type": "string",
                                "description": "Explication complète lisible par un humain."
                              }
                            }
                          },
                          "description": "`DATABASE_VALIDATION_NO_MATCH` ou `DATABASE_VALIDATION_PARTIAL_MATCH` le cas échéant ; vide en cas de correspondance complète."
                        },
                        "errors": {
                          "type": "array",
                          "description": "Présent uniquement lorsque certains (mais pas tous) des services sélectionnés ont échoué. Chaque entrée comporte `service_id`, `code`, `message` et `retryable`. Un service signalé ici est absent de `validations` et `services_used`, et n'est pas facturé. Ce tableau est le seul endroit où il apparaît, inspectez-le donc même lorsque `status` est `Approved`.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "service_id": {
                                "type": "string"
                              },
                              "code": {
                                "type": "string",
                                "example": "empty_provider_response"
                              },
                              "message": {
                                "type": "string"
                              },
                              "retryable": {
                                "type": "boolean",
                                "description": "`true` lorsque le service n'a produit aucune réponse et qu'une nouvelle tentative ultérieure peut réussir ; `false` lorsque la source a refusé les données envoyées et que la saisie doit d'abord être corrigée.",
                                "example": true
                              }
                            }
                          }
                        },
                        "services_used": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Identifiants de catalogue des services ayant retourné un résultat facturable. **Présent uniquement lorsque la requête a explicitement envoyé `services`.**"
                        },
                        "match_score": {
                          "type": "number",
                          "description": "Fraction (0,0–1,0) des services tentés ayant produit une correspondance complète (sur le numéro d'identification, sur le nom complet + la date de naissance combinés, ou sur l'adresse sans contradiction). **Présent uniquement lorsque la requête a explicitement envoyé `services`.**"
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Valeur renvoyée de `vendor_data` que vous avez envoyé."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "description": "Écho des `metadata` que vous avez envoyées."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "Full match (Approved)": {
                    "summary": "Par défaut save_api_request=true — objets `validations` par service",
                    "value": {
                      "request_id": "7f9a1c0e-1f2b-4f6e-9d3a-2b1c0e7f9a1c",
                      "database_validation": {
                        "status": "Approved",
                        "issuing_state": "BRA",
                        "validation_type": "one_by_one",
                        "screened_data": {
                          "tax_number": "12345678900",
                          "first_name": "John",
                          "last_name": "Doe",
                          "date_of_birth": "1980-01-01"
                        },
                        "match_type": "full_match",
                        "validations": [
                          {
                            "validation": {
                              "full_name": "full_match",
                              "date_of_birth": "full_match",
                              "identification_number": "full_match"
                            },
                            "outcome_code": "MATCH",
                            "outcome_detail": "200",
                            "service_id": "bra_cpf",
                            "service_name": "Brazil - CPF status check",
                            "source_data": {
                              "identification_number": "12345678900",
                              "first_name": "JOHN",
                              "last_name": "DOE",
                              "date_of_birth": "1980-01-01",
                              "lgpd_minor": false,
                              "minor_under_16": false,
                              "minor_under_18": false
                            }
                          }
                        ],
                        "warnings": []
                      },
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:30:00.000000+00:00"
                    }
                  },
                  "Explicit services (extended shape)": {
                    "summary": "Requête envoyée avec `services` — la réponse ajoute `services_used` et `match_score`",
                    "value": {
                      "request_id": "b3e7c1a2-9d4f-4f0b-8a6c-5e2d1f0a9b3e",
                      "database_validation": {
                        "status": "Approved",
                        "issuing_state": "BRA",
                        "validation_type": "one_by_one",
                        "screened_data": {
                          "tax_number": "12345678900",
                          "first_name": "John",
                          "last_name": "Doe",
                          "date_of_birth": "1980-01-01"
                        },
                        "match_type": "full_match",
                        "validations": [
                          {
                            "validation": {
                              "full_name": "full_match",
                              "date_of_birth": "full_match",
                              "identification_number": "full_match"
                            },
                            "outcome_code": "MATCH",
                            "outcome_detail": "200",
                            "service_id": "bra_cpf",
                            "service_name": "Brazil - CPF status check",
                            "source_data": {
                              "identification_number": "12345678900",
                              "first_name": "JOHN",
                              "last_name": "DOE",
                              "date_of_birth": "1980-01-01",
                              "lgpd_minor": false,
                              "minor_under_16": false,
                              "minor_under_18": false
                            }
                          }
                        ],
                        "warnings": [],
                        "services_used": [
                          "bra_cpf"
                        ],
                        "match_score": 1.0
                      },
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:30:00.000000+00:00"
                    }
                  },
                  "No match (Declined)": {
                    "summary": "L'enregistrement du registre ne correspond pas — valeur par défaut `no_match_action=DECLINE`",
                    "value": {
                      "request_id": "0a1b2c3d-4e5f-6789-abcd-ef0123456789",
                      "database_validation": {
                        "status": "Declined",
                        "issuing_state": "BRA",
                        "validation_type": "one_by_one",
                        "screened_data": {
                          "tax_number": "12345678900",
                          "first_name": "John",
                          "last_name": "Doe",
                          "date_of_birth": "1980-01-01"
                        },
                        "match_type": "no_match",
                        "validations": [
                          {
                            "validation": {
                              "full_name": "no_match",
                              "date_of_birth": "no_match",
                              "identification_number": "no_match"
                            },
                            "outcome_code": "NO_MATCH",
                            "outcome_detail": "200",
                            "service_id": "bra_cpf",
                            "service_name": "Brazil - CPF status check",
                            "source_data": {
                              "identification_number": "00987654321",
                              "first_name": "TOTALLY",
                              "last_name": "DIFFERENT NAME",
                              "date_of_birth": "1999-01-01",
                              "lgpd_minor": false,
                              "minor_under_16": false,
                              "minor_under_18": false
                            }
                          }
                        ],
                        "warnings": [
                          {
                            "feature": "DATABASE_VALIDATION",
                            "risk": "DATABASE_VALIDATION_NO_MATCH",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Database validation no match",
                            "long_description": "The system identified a no match in the database validation, requiring further investigation."
                          }
                        ]
                      },
                      "vendor_data": null,
                      "metadata": null,
                      "created_at": "2026-06-11T10:31:00.000000+00:00"
                    }
                  },
                  "Stateless (save_api_request=false)": {
                    "summary": "`validations` se réduit à un mappage de champs fusionné ; rien n'est stocké",
                    "value": {
                      "request_id": "c4d5e6f7-8901-2345-6789-abcdef012345",
                      "database_validation": {
                        "status": "Approved",
                        "issuing_state": "BRA",
                        "validation_type": "one_by_one",
                        "screened_data": {
                          "tax_number": "12345678900",
                          "first_name": "John",
                          "last_name": "Doe",
                          "date_of_birth": "1980-01-01"
                        },
                        "match_type": "full_match",
                        "validations": {
                          "full_name": "full_match",
                          "date_of_birth": "full_match",
                          "identification_number": "full_match"
                        },
                        "warnings": []
                      },
                      "vendor_data": null,
                      "metadata": null,
                      "created_at": "2026-06-11T10:32:00.000000+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation - rien n'est facturé. Les erreurs de champ préalables surviennent avant tout appel externe. Si chaque tentative restée sans réponse refuse explicitement la saisie, la réponse inclut plutôt `validation_errors` avec `code: provider_rejected_input` et `retryable: false` ; corrigez la saisie avant de réessayer. Les problèmes au niveau des champs utilisent l'enveloppe standard de DRF ; les problèmes de catalogue renvoient un tableau `services` (ainsi que `requires_onboarding` ou `services_requiring_consent` le cas échéant) ; les erreurs de champs manquants incluent `fields_required_by` associant chaque champ manquant aux services qui l'exigent ; les services qui nécessitent au moins un identifiant supplémentaire (par ex. `usa_states_credit_bureau`, qui ne peut pas vérifier un nom seul) renvoient `any_field_required_by` associant chaque service aux champs dont au moins un doit être présent ; les problèmes de format vérifiés par service renvoient `invalid_fields_by_service`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid issuing_state": {
                    "summary": "Pays non pris en charge — le message liste chaque code alpha-3 valide",
                    "value": {
                      "error": [
                        "Invalid issuing state. Valid options are: ARE, ARG, AUS, AUT, BEL, BGD, BOL, BRA, CAN, CHE, CHL, CHN, CIV, COL, CRI, CZE, DEU, DNK, DOM, ECU, ESP, FIN, FRA, GBR, GHA, GLB, GRC, GTM, HKG, HND, IDN, IND, IRL, ITA, KEN, KHM, MAR, MEX, MYS, NGA, NLD, NOR, NZL, OMN, PAN, PER, PHL, POL, PRT, PRY, QAT, SGP, SLV, SVK, SWE, THA, UGA, URY, USA, VEN, ZAF, ZMB, ZWE"
                      ]
                    }
                  },
                  "Missing required fields": {
                    "summary": "Union des champs requis pour l'ensemble des services sélectionnés, avec l'indication de champ universel",
                    "value": {
                      "error": [
                        "Missing required fields: tax_number (or use 'identification_number' which maps to 'tax_number' for BRA)"
                      ],
                      "fields_required_by": {
                        "tax_number": [
                          "bra_cpf"
                        ]
                      }
                    }
                  },
                  "Unknown service id": {
                    "summary": "`services` contient un identifiant qui ne figure pas dans le catalogue",
                    "value": {
                      "services": [
                        "Unknown service_id(s): ['bogus_service']"
                      ]
                    }
                  },
                  "Service not live for country": {
                    "summary": "`services` mentionne un service d'un autre pays (ou une entrée fictive)",
                    "value": {
                      "services": [
                        "Services not currently live for PER: ['bra_cpf']. Available services: ['per_dni', 'per_residential', 'per_tax_registration']"
                      ]
                    }
                  },
                  "Service requires onboarding": {
                    "summary": "Le service existe mais n'est pas encore activé pour votre organisation",
                    "value": {
                      "services": [
                        "Services require onboarding before they can be enabled for AUS: ['aus_australia_driver_licence']. Contact Didit support to activate them."
                      ],
                      "requires_onboarding": [
                        "aus_australia_driver_licence"
                      ]
                    }
                  },
                  "Consent missing": {
                    "summary": "Un service sélectionné est marqué avec requires_consent=true et `consent` n'était pas `true`",
                    "value": {
                      "consent": [
                        "Explicit end-user consent is required for these database validation services: ['chn_national_id']. Send `consent=true`."
                      ],
                      "services_requiring_consent": [
                        "chn_national_id"
                      ]
                    }
                  },
                  "Country format rule violation": {
                    "summary": "L'identifiant ne respecte pas la règle de format du pays (longueur/chiffres/regex)",
                    "value": {
                      "tax_number": [
                        "Invalid tax number for BRA: Brazilian CPF (exactly 11 digits). Must be exactly 11 characters long (got 10)."
                      ]
                    }
                  },
                  "Service-specific format violation": {
                    "summary": "Un champ ne respecte pas les exigences de format propres au service sélectionné",
                    "value": {
                      "error": [
                        "One or more fields do not match the format required by the selected service."
                      ],
                      "invalid_fields_by_service": {
                        "chn_national_id": [
                          "national_id_format"
                        ]
                      }
                    }
                  },
                  "Input refused by every attempt": {
                    "summary": "Corrigez les données saisies avant de réessayer",
                    "value": {
                      "error": "The source refused to run this query with the supplied input.",
                      "validation_errors": [
                        {
                          "service_id": "bra_cpf",
                          "code": "provider_rejected_input",
                          "message": "The source refused to run this query with the supplied input.",
                          "retryable": false
                        }
                      ]
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "properties": {
                    "error": {
                      "description": "Explication au niveau de la requête ou erreurs de champ de prévalidation.",
                      "oneOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    },
                    "validation_errors": {
                      "type": "array",
                      "description": "Présent lorsque chaque tentative restée sans réponse a rejeté la saisie après le preflight.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "service_id": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          },
                          "retryable": {
                            "type": "boolean",
                            "description": "Indique si réessayer plus tard peut résoudre cette défaillance de service. False signifie qu'il faut d'abord corriger l'entrée fournie."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout filtrage ou appel à un fournisseur.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Aucun service sélectionné n'a renvoyé de résultat exploitable. Examinez chaque entrée validation_errors avant de réessayer ; l'erreur HTTP 502 seule n'établit pas un échec temporaire. Une entrée empty_provider_response avec retryable: true indique des résultats indisponibles ou inexpliqués, y compris un fournisseur principal refusé suivi d'un repli indisponible. Les entrées héritées provider_invalid_input et provider_validation_error nécessitent plutôt une saisie corrigée et peuvent omettre retryable. Rien n'est facturé. Lorsque save_api_request=true, la tentative échouée est enregistrée sous forme de session avec le statut Not Finished. Les échecs partiels renvoient 200 avec database_validation.errors.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "validation_errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "service_id": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          },
                          "retryable": {
                            "type": "boolean",
                            "description": "Indique si réessayer plus tard peut résoudre cette défaillance de service. False signifie qu'il faut d'abord corriger l'entrée fournie."
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Provider returned no result": {
                    "summary": "Tous les services sélectionnés ont échoué",
                    "value": {
                      "error": "Database validation could not be performed. The external validation service did not return a result. Please try again later.",
                      "validation_errors": [
                        {
                          "service_id": "bra_cpf",
                          "code": "empty_provider_response",
                          "message": "The provider did not return a database validation result.",
                          "retryable": true
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/phone/send/": {
      "post": {
        "summary": "Envoyer le code par téléphone",
        "description": "Envoyez un code à usage unique (OTP) à un numéro de téléphone via WhatsApp, SMS ou un autre canal pris en charge, puis vérifiez-le avec [`POST /v3/phone/check/`](/fr/standalone-apis/phone-check).\n\n**Comment fonctionnent l'envoi et la vérification.** L'état de la vérification est associé à votre application et au `phone_number` au format E.164 — l'appel de vérification ne prend pas de `request_id`. Chaque nouvel envoi crée une vérification en attente valable pendant **5 minutes** : appelez la vérification avec le même numéro et le code reçu par l'utilisateur avant la fermeture de la fenêtre. Appeler à nouveau l'envoi pour le même numéro alors qu'une vérification est en attente renvoie un code pour cette même vérification (`status: \"Retry\"`, même `request_id`). Au maximum une nouvelle tentative est associée de cette façon (deux envois au total) ; un envoi supplémentaire démarre une nouvelle vérification avec un nouveau `request_id`. La fenêtre de 5 minutes est calculée à partir du premier envoi et n'est pas prolongée par les nouvelles tentatives.\n\n**Canaux de livraison.** `options.preferred_channel` sélectionne le canal (`whatsapp` par défaut ; `sms`, `telegram`, `voice`, `rcs`, `viber` et `zalo` sont également pris en charge). Lorsque le canal préféré n'est pas disponible pour le pays ou le numéro de destination, la livraison bascule automatiquement vers le SMS — l'envoi indique toujours `Success`, et le canal réellement utilisé est indiqué dans la réponse de vérification (`phone.verification_method` et les événements `lifecycle`).\n\n**Personnalisation de marque.** Les codes SMS comportent le nom d'expéditeur SMS de votre application, configuré dans la Business Console, sans frais supplémentaires. Transmettez `options.sms_sender_name` pour signer un code avec un autre nom, ou `options.use_white_label_customization: true` pour utiliser par défaut votre nom public en marque blanche lorsqu'aucun nom d'expéditeur n'est défini. Les codes WhatsApp utilisent un message fixe ; associez votre propre numéro WhatsApp Business dans la Business Console pour les envoyer depuis le nom et le numéro de votre entreprise ; ces envois sont facturés uniquement au tarif Didit.\n\n**Statuts d'envoi.** `Success` — OTP envoyé pour une nouvelle vérification ; `Retry` — OTP renvoyé pour la vérification en attente ; `Blocked` — la couche antifraude a refusé l'envoi (voir `reason`, par ex. `repeated_attempts`, `suspicious`, `spam`). Un envoi `Blocked` finalise immédiatement la vérification avec le statut `Declined` et un avertissement de risque élevé, de sorte qu'une vérification ultérieure renvoie `Expired or Not Found`.\n\n**Facturation.** Le prix dépend du pays de destination et du canal par lequel le message est effectivement envoyé — consultez [Tarifs de la Vérification du téléphone](/fr/getting-started/phone-verification-pricing). Seuls les envois `Blocked` sont garantis gratuits : toute autre tentative d'envoi non facturée est débitée lors de la finalisation ou de l'expiration de la vérification, même si la livraison n'a jamais été confirmée ou si le prestataire de livraison a signalé le message comme non distribuable. Les vérifications sont toujours gratuites. Par mesure de lutte contre les abus, la vérification du téléphone est désactivée jusqu'à la première recharge de votre organisation (`403`).\n\n**Persistance de session.** Chaque nouvelle vérification est conservée sous la forme d'une session de type API : `request_id` est un véritable identifiant de session que vous pouvez transmettre à `GET /v3/session/{sessionId}/decision/`, la vérification apparaît dans la Business Console et les webhooks `status.updated` sont déclenchés au fur et à mesure de sa progression.\n\n**Sandbox.** Les clés API sandbox contournent la livraison et la facturation : après validation de la requête (une saisie mal formée renvoie toujours `400`), l'endpoint renvoie un payload statique `Success` avec un `request_id` aléatoire ; aucun message n'est envoyé et rien n'est conservé. Utilisez le code `123456` lors de la vérification sandbox.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou invalides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) — cette API ne renvoie jamais `401`.\n\n**Limites de débit.** Budget d'écriture partagé de 300 requêtes/min par clé API sur tous les endpoints POST/PATCH/DELETE, plus un plafond anti-abus de 4 tentatives d'envoi par numéro de téléphone et par heure ; tout dépassement renvoie `429`.",
        "operationId": "post_v3phone_send",
        "x-didit-sdk": {
          "resource": "phone",
          "method": "send_code",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/phone/send/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"phone_number\": \"+14155552671\",\n    \"options\": {\n      \"code_size\": 6,\n      \"preferred_channel\": \"whatsapp\",\n      \"locale\": \"en-US\"\n    },\n    \"vendor_data\": \"user-1234\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.phone.send_code(\n    phone_number=\"+14155552671\",\n    options={\n        \"locale\": \"en-US\",\n        \"preferred_channel\": \"whatsapp\",\n    },\n    vendor_data=\"user-1234\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.phone.sendCode({\n  phone_number: \"+14155552671\",\n  options: {\n    locale: \"en-US\",\n    preferred_channel: \"whatsapp\",\n  },\n  vendor_data: \"user-1234\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Phone.SendCode(ctx, didit.PhoneSendCodeParams{\n\tPhoneNumber: \"+14155552671\",\n\tOptions: didit.Some(didit.PhoneSendCodeParamsOptions{\n\t\tLocale:           didit.String(\"en-US\"),\n\t\tPreferredChannel: didit.Some(didit.PhoneSendCodeParamsOptionsPreferredChannel(\"whatsapp\")),\n\t}),\n\tVendorData: didit.String(\"user-1234\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.PhoneSendCodeParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.phone().sendCode(PhoneSendCodeParams.builder()\n        .phoneNumber(\"+14155552671\")\n        .options(PhoneSendCodeParams.Options.builder()\n                .locale(\"en-US\")\n                .preferredChannel(PhoneSendCodeParams.Options.PreferredChannel.of(\"whatsapp\"))\n                .build())\n        .vendorData(\"user-1234\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->phone->sendCode([\n    'phone_number' => '+14155552671',\n    'options' => [\n        'locale' => 'en-US',\n        'preferred_channel' => 'whatsapp',\n    ],\n    'vendor_data' => 'user-1234',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.phone.send_code(\n  phone_number: \"+14155552671\",\n  options: {\n    locale: \"en-US\",\n    preferred_channel: \"whatsapp\",\n  },\n  vendor_data: \"user-1234\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Phone.SendCodeAsync(new PhoneSendCodeParams\n{\n    PhoneNumber = \"+14155552671\",\n    Options = new PhoneSendCodeParamsOptions\n    {\n        Locale = \"en-US\",\n        PreferredChannel = new PhoneSendCodeParamsOptionsPreferredChannel(\"whatsapp\"),\n    },\n    VendorData = \"user-1234\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "maxLength": 20,
                    "description": "Numéro de téléphone du destinataire au format E.164 — avec un `+` initial et l'indicatif du pays (par ex., `+14155552671`). Les numéros sont validés et normalisés au format E.164 ; les numéros invalides ou impossibles à analyser renvoient une erreur `400` avec une erreur sur le champ `phone_number`.",
                    "example": "+14155552671"
                  },
                  "options": {
                    "type": "object",
                    "description": "Options de livraison de l'OTP. Tous les champs sont facultatifs.",
                    "properties": {
                      "code_size": {
                        "type": "integer",
                        "minimum": 4,
                        "maximum": 8,
                        "default": 6,
                        "description": "Nombre de chiffres dans l'OTP."
                      },
                      "locale": {
                        "type": "string",
                        "maxLength": 5,
                        "pattern": "^[a-z]{2,3}(-[A-Z]{2,3})?$",
                        "description": "Paramètre régional BCP-47 utilisé pour localiser le message de vérification (par ex. `en-US`, `fr`, `es`). Les formats non valides renvoient `400`.",
                        "example": "en-US"
                      },
                      "preferred_channel": {
                        "type": "string",
                        "enum": [
                          "whatsapp",
                          "sms",
                          "telegram",
                          "voice",
                          "rcs",
                          "viber",
                          "zalo"
                        ],
                        "default": "whatsapp",
                        "description": "Canal de livraison préféré. Si le canal est indisponible pour le pays ou le numéro de destination, le message bascule automatiquement sur SMS — l'envoi indique toujours `Success`."
                      },
                      "use_white_label_customization": {
                        "type": "boolean",
                        "default": false,
                        "description": "Lorsque la valeur est `true`, l'envoi est en marque blanche : si votre application ne dispose pas de nom d'expéditeur SMS, le SMS mentionne à la place votre nom public en marque blanche (\"123456 est votre code de vérification pour Acme Bank\"). Votre nom d'expéditeur SMS, lorsqu'il est défini, est utilisé avec ou sans cet indicateur. S'applique aux messages SMS, y compris lors d'un repli par SMS depuis un autre canal ; les codes WhatsApp sont envoyés avec un message fixe et ne comportent pas d'image de marque. Valeur par défaut : `false`."
                      },
                      "sms_sender_name": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 30,
                        "example": "Acme Bank",
                        "description": "Le nom affiché dans le SMS de ce code (« 123456 est votre code de vérification pour Acme Bank »), au lieu du nom d'expéditeur SMS de votre application. Gratuit. 1 à 30 caractères : lettres, chiffres, espaces et ' & - ! uniquement, pas uniquement des chiffres, avec des espaces simples entre les mots ; toute autre valeur renvoie `400` et aucun code n'est envoyé. En cas d'omission, de valeur `null` ou vide, le nom d'expéditeur SMS de votre application est utilisé. Chaque application peut commencer à utiliser jusqu'à deux nouveaux noms par jour (UTC) ; au-delà, le code est envoyé avec le nom de votre application. S'applique aux messages SMS, y compris lors d'un basculement par SMS depuis un autre canal ; les codes WhatsApp ne comportent pas de marque.",
                        "pattern": "^$|^(?![\\d ]+$)[\\p{L}\\p{N}'&!-]+( [\\p{L}\\p{N}'&!-]+)*$"
                      }
                    }
                  },
                  "signals": {
                    "type": "object",
                    "description": "Signaux d'appareil et de réseau optionnels concernant l'utilisateur final, transmis à la couche antifraude pour améliorer la détection de trafic abusif ou automatisé. Tous les champs sont optionnels.",
                    "properties": {
                      "ip": {
                        "type": "string",
                        "description": "Adresse de l'appareil de l'utilisateur final. IPv4 ou IPv6.",
                        "example": "192.0.2.1"
                      },
                      "device_id": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Identifiant unique de l'appareil de l'utilisateur final. Android : `ANDROID_ID` ; iOS : `identifierForVendor`.",
                        "example": "8F0B8FDD-C2CB-4387-B20A-56E9B2E5A0D2"
                      },
                      "device_platform": {
                        "type": "string",
                        "enum": [
                          "android",
                          "ios",
                          "ipados",
                          "tvos",
                          "web"
                        ],
                        "description": "Plateforme de l'appareil de l'utilisateur final."
                      },
                      "device_model": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Modèle de l'appareil de l'utilisateur final.",
                        "example": "iPhone17,2"
                      },
                      "os_version": {
                        "type": "string",
                        "maxLength": 64,
                        "description": "Version du système d'exploitation de l'appareil de l'utilisateur final.",
                        "example": "18.0.1"
                      },
                      "app_version": {
                        "type": "string",
                        "maxLength": 64,
                        "description": "Version de votre application.",
                        "example": "1.2.34"
                      },
                      "user_agent": {
                        "type": "string",
                        "maxLength": 512,
                        "description": "Agent utilisateur du navigateur ou de l'application de l'utilisateur final.",
                        "example": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1"
                      }
                    }
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Identifiant optionnel contrôlé par l'appelant (votre identifiant utilisateur interne, un e-mail, un UUID, etc.) persisté sur la session et renvoyé dans la réponse d'envoi, la réponse de vérification de correspondance, les webhooks et la Business Console. Utilisez-le pour corréler le `request_id` de Didit avec votre dossier utilisateur."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "Objet JSON libre optionnel conservé sur la session et renvoyé dans la réponse d'envoi, la réponse de vérification de correspondance, les webhooks et la Business Console."
                  }
                },
                "required": [
                  "phone_number"
                ]
              },
              "examples": {
                "WhatsApp (default)": {
                  "summary": "OTP à 6 chiffres via WhatsApp, avec basculement automatique vers les SMS",
                  "value": {
                    "phone_number": "+14155552671",
                    "options": {
                      "preferred_channel": "whatsapp",
                      "locale": "en-US"
                    },
                    "vendor_data": "user-1234"
                  }
                },
                "SMS with custom code length": {
                  "summary": "Forcer la livraison par SMS avec un code à 4 chiffres",
                  "value": {
                    "phone_number": "+34699999999",
                    "options": {
                      "preferred_channel": "sms",
                      "code_size": 4,
                      "locale": "es"
                    }
                  }
                },
                "With fraud signals": {
                  "summary": "Transmettez les signaux de l'appareil pour renforcer le filtrage antifraude",
                  "value": {
                    "phone_number": "+14155552671",
                    "signals": {
                      "ip": "192.0.2.1",
                      "device_id": "8F0B8FDD-C2CB-4387-B20A-56E9B2E5A0D2",
                      "device_platform": "ios",
                      "device_model": "iPhone17,2",
                      "os_version": "18.0.1",
                      "app_version": "1.2.34"
                    },
                    "vendor_data": "user-1234"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Envoi pris en compte. Examinez `status` : `Success` et `Retry` indiquent qu'un code est en cours d'envoi ; `Blocked` signifie que la couche antifraude a refusé et que la vérification est déjà finalisée en tant que `Declined`. `request_id` est l'identifiant de session persistant (même identifiant lors d'un `Retry`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneVerificationSendResponse"
                },
                "examples": {
                  "Success": {
                    "summary": "OTP envoyé pour une nouvelle vérification",
                    "value": {
                      "request_id": "e39cb057-92fc-4b59-b84e-02fec29a0f24",
                      "status": "Success",
                      "reason": null,
                      "vendor_data": "user-1234",
                      "metadata": null
                    }
                  },
                  "Retry": {
                    "summary": "Deuxième envoi pour le même numéro dans la fenêtre de 5 minutes — même request_id",
                    "value": {
                      "request_id": "e39cb057-92fc-4b59-b84e-02fec29a0f24",
                      "status": "Retry",
                      "reason": null,
                      "vendor_data": "user-1234",
                      "metadata": null
                    }
                  },
                  "Blocked": {
                    "summary": "Refus anti-fraude — vérification finalisée avec le statut Declined, rien n'est facturé",
                    "value": {
                      "request_id": "0d8af1f4-0c43-46d7-b75c-6e4e22c0a7b3",
                      "status": "Blocked",
                      "reason": "repeated_attempts",
                      "vendor_data": "user-1234",
                      "metadata": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Une entrée malformée renvoie l'enveloppe d'erreur de champ de DRF (un tableau de messages par champ en cause, imbriqué sous `options` pour les erreurs d'option). Un numéro dont l'analyse réussit mais qui est rejeté au moment de l'envoi (inaccessible ou type de ligne non éligible tel qu'un code court) renvoie plutôt une enveloppe `{\"detail\": ...}`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid phone number (field error)": {
                    "summary": "Le numéro n'est pas au format E.164 valide",
                    "value": {
                      "phone_number": [
                        "Invalid phone number provided."
                      ]
                    }
                  },
                  "Missing phone number": {
                    "summary": "`phone_number` non inclus dans le corps",
                    "value": {
                      "phone_number": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid options": {
                    "summary": "`code_size` hors limites, `locale` malformée, `preferred_channel` inconnu",
                    "value": {
                      "options": {
                        "code_size": [
                          "Ensure this value is less than or equal to 8."
                        ],
                        "locale": [
                          "Ensure this field has no more than 5 characters."
                        ],
                        "preferred_channel": [
                          "\"carrier_pigeon\" is not a valid choice."
                        ]
                      }
                    }
                  },
                  "Number rejected at send time": {
                    "summary": "Format E.164 valide mais le numéro ne peut pas recevoir d'OTP",
                    "value": {
                      "detail": "Invalid phone number provided."
                    }
                  },
                  "Ineligible line type": {
                    "summary": "Le type de ligne ne peut pas recevoir d'OTP (par exemple, numéro court)",
                    "value": {
                      "detail": "Invalid phone line type provided."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant (`{\"detail\": ...}`) ; une clé incorrecte, révoquée ou expirée renvoie `401`. Également renvoyé avant tout envoi lorsque l'organisation n'a jamais rechargé son solde (protection anti-abus) ou lorsque son solde ne permet pas de couvrir le prix d'envoi vers la destination (`{\"error\": ...}`).",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Top-up required": {
                    "summary": "La vérification du téléphone reste désactivée jusqu'à la première recharge de l'organisation",
                    "value": {
                      "detail": "To protect against abuse, phone verification is disabled until your first top-up."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir le prix d'envoi",
                    "value": {
                      "error": "You don't have enough credits to perform this request."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements disposent d'un budget distinct de 600). De plus, un plafond anti-abus de 4 tentatives de vérification par numéro de téléphone par heure s'applique en amont. La réponse contient les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`. Remarque : les en-têtes `X-RateLimit-*`/`Retry-After` accompagnent uniquement l'erreur 429 de la limite d'écriture de 300/min ; l'erreur 429 du plafond par numéro ne comporte aucun en-tête de limitation de débit.",
            "content": {
              "application/json": {
                "examples": {
                  "Per-number cap": {
                    "summary": "Plus de 4 tentatives de vérification pour le même numéro au cours de la dernière heure",
                    "value": {
                      "detail": "Maximum verification attempts reached for this phone number. Only 4 authentication attempts are allowed per hour. Try again later or use a different number."
                    }
                  },
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Le fournisseur de vérification du téléphone est temporairement indisponible - une réponse 5xx, un délai d'attente dépassé ou une erreur de connexion persistante après les tentatives automatiques intégrées. Vous pouvez réessayer en toute sécurité ; rien n'est facturé et aucune tentative n'est décomptée.",
            "content": {
              "application/json": {
                "examples": {
                  "Provider outage": {
                    "summary": "Le fournisseur n'a pas répondu à la requête d'envoi",
                    "value": {
                      "detail": "Phone verification is temporarily unavailable. Please try again shortly.",
                      "code": "phone_provider_unavailable"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Échec inattendu lors de la création de la vérification ne correspondant pas à une panne connue du fournisseur. Peut être réessayé en toute sécurité.",
            "content": {
              "application/json": {
                "examples": {
                  "Provider error": {
                    "summary": "La livraison de l'OTP n'a pas pu être initiée",
                    "value": {
                      "detail": "Error creating phone verification"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/phone/check/": {
      "post": {
        "summary": "Vérifier le code de téléphone",
        "description": "Vérifiez l'OTP délivré par [`POST /v3/phone/send/`](/fr/standalone-apis/phone-send) et obtenez le résultat final de la vérification ainsi que les renseignements sur le téléphone : nom de l'opérateur et type de ligne, indicateurs de numéro virtuel (VoIP) et jetable, et utilisation en double du numéro parmi vos sessions.\n\n**Comment la vérification retrouve l'enregistrement.** La correspondance s'effectue via votre application et le `phone_number` au format E.164 (`request_id` n'est pas un paramètre d'entrée). La vérification en attente la plus récente créée au cours des **5 dernières minutes** est contrôlée. S'il n'en existe aucune (jamais envoyée, déjà finalisée ou datant de plus de 5 minutes), l'endpoint renvoie `200` avec `status: \"Expired or Not Found\"`.\n\n**Quota de tentatives.** Chaque vérification autorise **3 tentatives de code**. Les deux premiers codes incorrects renvoient `status: \"Failed\"` avec le nombre de tentatives restantes et `phone: null` ; le troisième code incorrect finalise la vérification avec le statut `Declined`, assorti d'un avertissement `VERIFICATION_CODE_ATTEMPTS_EXCEEDED`, et renvoie le rapport téléphonique complet.\n\n**Résultats.** `Approved` : code correct et aucun risque entraînant un refus. `Declined` : définitif, le code était correct mais un risque entraînant un refus a été détecté (une action `DECLINE` ci-dessous, un numéro sur liste de blocage ou à haut risque), ou le quota de tentatives a été épuisé. `Failed` : mauvais code, tentatives restantes. `Expired or Not Found` : rien à vérifier. Pour `Approved`/`Declined`, `request_id` est égal au `request_id` de l'envoi (l'identifiant de session) et `phone` contient le rapport complet (`carrier`, `is_virtual`, `is_disposable`, `warnings`, `lifecycle`, `matches`) ; pour `Failed` et `Expired or Not Found`, `request_id` est un UUID aléatoire unique.\n\n**Actions en cas de risque.** `duplicated_phone_number_action`, `disposable_number_action` et `voip_number_action` déterminent ce qui se passe lorsque le risque correspondant est détecté sur un code correct : `DECLINE` bascule le statut final à `Declined` ; `NO_ACTION` (valeur par défaut) enregistre le risque dans `phone.warnings` sans affecter le statut.\n\n**Facturation.** Les contrôles sont gratuits, la livraison est facturée du côté de l'envoi (voir [Tarifs de la vérification du téléphone](/fr/getting-started/phone-verification-pricing)).\n\n**Persistance de la session.** Un contrôle finalisé met à jour la session créée par l'envoi (visible dans la Business Console, consultable via `GET /v3/session/{sessionId}/decision/`) et déclenche un webhook `status.updated`.\n\n**Sandbox.** Les clés API de sandbox ignorent tout traitement : tout code bien formé (de 4 à 8 chiffres, `123456` inclus) renvoie un payload statique `Approved` avec un objet `phone` simplifié et plat (`status`, `phone_number`, `country_code`, `carrier_name`, `line_type`, `flags`) ; une entrée mal formée renvoie toujours `400`. Rien n'est conservé.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou non valides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) ; cette API ne renvoie jamais `401`.\n\n**Limites de débit.** Quota partagé d'écriture de 300 requêtes/min par clé API, en plus de la limite anti-abus en amont de 4 tentatives par numéro et par heure ; dépasser l'une ou l'autre renvoie `429`.\n\n**Empreinte sociale.** Définissez `enable_social` sur `true` pour ajouter un bloc `phone_social` : les plateformes en ligne sur lesquelles ce numéro est enregistré, avec le nombre par catégorie et les détails de profil disponibles. `profiles_registered: 0` signifie que les plateformes ont été vérifiées et que le numéro n'a été trouvé sur aucune d'entre elles - une réponse valide et facturable. Le bloc est absent lorsque le module complémentaire n'a pas été demandé ou que le contrôle n'a pas pu aboutir, et il n'est pas facturé dans ce cas. La facturation ajoute une unité `phone_social` par requête au prix propre de cet endpoint.",
        "operationId": "post_v3phone_check",
        "x-didit-sdk": {
          "resource": "phone",
          "method": "check_code",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/phone/check/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"phone_number\": \"+14155552671\",\n    \"code\": \"123456\",\n    \"voip_number_action\": \"DECLINE\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.phone.check_code(\n    phone_number=\"+14155552671\",\n    code=\"123456\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.phone.checkCode({\n  phone_number: \"+14155552671\",\n  code: \"123456\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Phone.CheckCode(ctx, didit.PhoneCheckCodeParams{\n\tPhoneNumber: \"+14155552671\",\n\tCode:        \"123456\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.PhoneCheckCodeParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.phone().checkCode(PhoneCheckCodeParams.builder()\n        .phoneNumber(\"+14155552671\")\n        .code(\"123456\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->phone->checkCode([\n    'phone_number' => '+14155552671',\n    'code' => '123456',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.phone.check_code(\n  phone_number: \"+14155552671\",\n  code: \"123456\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Phone.CheckCodeAsync(new PhoneCheckCodeParams\n{\n    PhoneNumber = \"+14155552671\",\n    Code = \"123456\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "maxLength": 20,
                    "description": "Le même numéro de téléphone que celui utilisé dans l'appel [`POST /v3/phone/send/`](/fr/standalone-apis/phone-send) correspondant, au format E.164. C'est ce qui associe la vérification à l'envoi.",
                    "example": "+14155552671"
                  },
                  "code": {
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 8,
                    "pattern": "^[0-9]{4,8}$",
                    "description": "L'OTP reçu par l'utilisateur final. Doit comporter entre 4 et 8 chiffres numériques — toute autre valeur renvoie `400` sans décompter de tentative. Un code bien formé mais incorrect renvoie `200` avec `status: \"Failed\"` et décompte l'une des 3 tentatives.",
                    "example": "123456"
                  },
                  "duplicated_phone_number_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Que faire lorsque le même numéro a déjà été utilisé par un autre utilisateur (`vendor_data` différent) de votre application. `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le risque dans `phone.warnings` et renseigne `phone.matches`."
                  },
                  "disposable_number_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Ce qu'il faut faire lorsque la recherche d'opérateur signale le numéro comme une ligne temporaire ou jetable (`phone.is_disposable`). `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le risque dans `phone.warnings`."
                  },
                  "voip_number_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Ce qu'il faut faire lorsque la recherche d'opérateur indique un type de ligne virtuelle — `voip`, `isp` ou `vpn` (`phone.is_virtual`). `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le risque dans `phone.warnings`."
                  },
                  "enable_enrichment": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lorsque la valeur est `true`, exécute également une analyse de renseignements téléphoniques sur le numéro : un score de risque, le type de ligne, un éventuel portage récent et un indice de confiance. Facturé comme une unité `phone_intelligence_api` par requête ($0.05 au prix catalogue) en plus du prix propre à cet endpoint. La requête renvoie `403` lorsque votre solde ne permet pas de la couvrir.",
                    "example": false
                  },
                  "phone_intelligence_score_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque le score de risque de l'intelligence téléphonique est supérieur au seuil. `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le signal sans refuser. Ne prend effet que lorsque `enable_enrichment` est `true`."
                  },
                  "phone_type_risk_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque le numéro correspond à un type de ligne à haut risque. `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le signal sans refuser. Ne prend effet que lorsque `enable_enrichment` est `true`."
                  },
                  "recent_port_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque le numéro a été récemment porté vers un autre opérateur. `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le signal sans refuser. Ne prend effet que lorsque `enable_enrichment` est `true`."
                  },
                  "low_phone_trust_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque l'indice de confiance de l'intelligence téléphonique est inférieur ou égal au seuil. `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le signal sans refuser. Ne prend effet que lorsque `enable_enrichment` est `true`."
                  },
                  "enable_social": {
                    "type": "boolean",
                    "default": false,
                    "description": "Si true, recherche également l'empreinte sociale du numéro : les plateformes de messagerie, sociales, d'e-commerce et professionnelles sur lesquelles il est enregistré. Facturé comme une unité `phone_social` par requête en plus du prix propre de cet endpoint.",
                    "example": true
                  },
                  "phone_no_social_presence_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque la vérification de l'empreinte sociale ne trouve le numéro enregistré sur aucune des plateformes couvertes. Seuls NO_ACTION et DECLINE sont acceptés sur cet endpoint ; REVIEW est disponible sur la clé de configuration du workflow du même nom."
                  }
                },
                "required": [
                  "phone_number",
                  "code"
                ]
              },
              "examples": {
                "Default": {
                  "summary": "Enregistrer tous les risques sans jamais refuser automatiquement",
                  "value": {
                    "phone_number": "+14155552671",
                    "code": "123456"
                  }
                },
                "Strict risk policy": {
                  "summary": "Refuser automatiquement les lignes VoIP et jetables",
                  "value": {
                    "phone_number": "+14155552671",
                    "code": "123456",
                    "voip_number_action": "DECLINE",
                    "disposable_number_action": "DECLINE"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vérification terminée — les codes erronés et les vérifications manquantes renvoient également `200` ; inspectez `status`, et non le code HTTP. `phone` n'est renseigné que pour les résultats finalisés (`Approved`/`Declined`), vaut `null` pour `Failed`, et est absent pour `Expired or Not Found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneVerificationCheckResponse"
                },
                "examples": {
                  "Approved": {
                    "summary": "Code correct — rapport téléphonique complet avec opérateur, cycle de vie et correspondances",
                    "value": {
                      "request_id": "e39cb057-92fc-4b59-b84e-02fec29a0f24",
                      "status": "Approved",
                      "message": "The verification code is correct.",
                      "phone": {
                        "status": "Approved",
                        "phone_number_prefix": "+1",
                        "phone_number": "4155552671",
                        "full_number": "+14155552671",
                        "country_code": "US",
                        "country_name": "United States",
                        "carrier": {
                          "name": "AT&T",
                          "type": "mobile"
                        },
                        "is_disposable": false,
                        "is_virtual": false,
                        "verification_method": "whatsapp",
                        "verification_attempts": 1,
                        "verified_at": "2026-06-12T01:24:47.311323Z",
                        "warnings": [],
                        "lifecycle": [
                          {
                            "type": "PHONE_VERIFICATION_MESSAGE_SENT",
                            "timestamp": "2026-06-12T01:23:39.580554+00:00",
                            "details": {
                              "status": "Success",
                              "reason": null,
                              "channel": "whatsapp",
                              "actual_channel": "whatsapp"
                            },
                            "fee": 0.0509
                          },
                          {
                            "type": "PHONE_DELIVERY_DELIVERED",
                            "timestamp": "2026-06-12T01:23:43.118220+00:00",
                            "details": {
                              "channel": "whatsapp",
                              "status": "delivered"
                            },
                            "fee": 0
                          },
                          {
                            "type": "VALID_CODE_ENTERED",
                            "timestamp": "2026-06-12T01:24:47.311201+00:00",
                            "details": {
                              "code_tried": "123456",
                              "status": "Approved"
                            },
                            "fee": 0
                          },
                          {
                            "type": "PHONE_VERIFICATION_APPROVED",
                            "timestamp": "2026-06-12T01:24:47.384292+00:00",
                            "details": null,
                            "fee": 0
                          }
                        ],
                        "matches": []
                      },
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:47.401719+00:00"
                    }
                  },
                  "Failed (attempts remaining)": {
                    "summary": "Code erroné — l'utilisateur peut réessayer ; request_id est ici un UUID à usage unique",
                    "value": {
                      "request_id": "11111111-2222-3333-4444-555555555555",
                      "status": "Failed",
                      "message": "The verification code is incorrect. Attempts remaining: 2",
                      "phone": null,
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:21.512340+00:00"
                    }
                  },
                  "Declined (max attempts)": {
                    "summary": "Troisième code erroné — vérification finalisée avec le statut Refusé",
                    "value": {
                      "request_id": "e39cb057-92fc-4b59-b84e-02fec29a0f24",
                      "status": "Declined",
                      "message": "The verification code is incorrect. Maximum attempts reached.",
                      "phone": {
                        "status": "Declined",
                        "phone_number_prefix": "+1",
                        "phone_number": "4155552671",
                        "full_number": "+14155552671",
                        "country_code": "US",
                        "country_name": "United States",
                        "carrier": {
                          "name": "AT&T",
                          "type": "mobile"
                        },
                        "is_disposable": false,
                        "is_virtual": false,
                        "verification_method": "whatsapp",
                        "verification_attempts": 1,
                        "verified_at": null,
                        "warnings": [
                          {
                            "feature": "PHONE",
                            "risk": "VERIFICATION_CODE_ATTEMPTS_EXCEEDED",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Verification code attempts exceeded",
                            "long_description": "The system detected that the phone number has exceeded the maximum number of verification code attempts."
                          }
                        ],
                        "lifecycle": [
                          {
                            "type": "PHONE_VERIFICATION_MESSAGE_SENT",
                            "timestamp": "2026-06-12T01:23:39.580554+00:00",
                            "details": {
                              "status": "Success",
                              "reason": null,
                              "channel": "whatsapp",
                              "actual_channel": "whatsapp"
                            },
                            "fee": 0.0509
                          },
                          {
                            "type": "INVALID_CODE_ENTERED",
                            "timestamp": "2026-06-12T01:24:01.118220+00:00",
                            "details": {
                              "code_tried": "111111",
                              "status": "Failed"
                            },
                            "fee": 0
                          },
                          {
                            "type": "INVALID_CODE_ENTERED",
                            "timestamp": "2026-06-12T01:24:21.512340+00:00",
                            "details": {
                              "code_tried": "222222",
                              "status": "Failed"
                            },
                            "fee": 0
                          },
                          {
                            "type": "INVALID_CODE_ENTERED",
                            "timestamp": "2026-06-12T01:24:47.311201+00:00",
                            "details": {
                              "code_tried": "333333",
                              "status": "Failed"
                            },
                            "fee": 0
                          },
                          {
                            "type": "PHONE_VERIFICATION_DECLINED",
                            "timestamp": "2026-06-12T01:24:47.384292+00:00",
                            "details": {
                              "reason": "VERIFICATION_CODE_ATTEMPTS_EXCEEDED"
                            },
                            "fee": 0
                          }
                        ],
                        "matches": []
                      },
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:47.401719+00:00"
                    }
                  },
                  "Declined (risk policy)": {
                    "summary": "Code correct, mais la ligne est VoIP et voip_number_action=DECLINE",
                    "value": {
                      "request_id": "7f1c9d2e-44a1-4b6e-9a3e-5b8e6f1c2d3a",
                      "status": "Declined",
                      "message": "The verification code is correct.",
                      "phone": {
                        "status": "Declined",
                        "phone_number_prefix": "+1",
                        "phone_number": "5005550006",
                        "full_number": "+15005550006",
                        "country_code": "US",
                        "country_name": "United States",
                        "carrier": {
                          "name": "CLEC LLC",
                          "type": "voip"
                        },
                        "is_disposable": false,
                        "is_virtual": true,
                        "verification_method": "sms",
                        "verification_attempts": 1,
                        "verified_at": "2026-06-12T01:24:47.311323Z",
                        "warnings": [
                          {
                            "feature": "PHONE",
                            "risk": "VOIP_NUMBER_DETECTED",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "VoIP number detected",
                            "long_description": "The system detected that the phone number is a VoIP number, which is not allowed."
                          }
                        ],
                        "lifecycle": [
                          {
                            "type": "PHONE_VERIFICATION_MESSAGE_SENT",
                            "timestamp": "2026-06-12T01:23:39.580554+00:00",
                            "details": {
                              "status": "Success",
                              "reason": null,
                              "channel": "whatsapp",
                              "actual_channel": "sms"
                            },
                            "fee": 0.0509
                          },
                          {
                            "type": "VALID_CODE_ENTERED",
                            "timestamp": "2026-06-12T01:24:47.311201+00:00",
                            "details": {
                              "code_tried": "123456",
                              "status": "Approved"
                            },
                            "fee": 0
                          },
                          {
                            "type": "PHONE_VERIFICATION_DECLINED",
                            "timestamp": "2026-06-12T01:24:47.384292+00:00",
                            "details": {
                              "reason": "VOIP_NUMBER_DETECTED"
                            },
                            "fee": 0
                          }
                        ],
                        "matches": []
                      },
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:47.401719+00:00"
                    }
                  },
                  "Expired or Not Found": {
                    "summary": "Aucune vérification en attente pour ce numéro au cours des 5 dernières minutes",
                    "value": {
                      "request_id": "69cc35c6-280a-47a6-ab8c-4f32abc02ed0",
                      "status": "Expired or Not Found",
                      "message": "No pending phone verification found in the last 5 minutes.",
                      "vendor_data": null,
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:47.311323+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — enveloppe d'erreur de champ de DRF : un tableau de messages par champ concerné.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid code format": {
                    "summary": "`code` n'est pas composé de 4 à 8 chiffres",
                    "value": {
                      "code": [
                        "Invalid code format. Enter 4 to 8 numeric digits."
                      ]
                    }
                  },
                  "Invalid phone number": {
                    "summary": "`phone_number` n'est pas au format E.164 valide",
                    "value": {
                      "phone_number": [
                        "Invalid phone number provided."
                      ]
                    }
                  },
                  "Invalid action": {
                    "summary": "Les actions de risque acceptent uniquement NO_ACTION ou DECLINE",
                    "value": {
                      "voip_number_action": [
                        "\"REVIEW\" is not a valid choice."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les vérifications sont gratuites, aucun contrôle de crédit n'est donc effectué ici.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements disposent d'un budget distinct de 600). De plus, un plafond anti-abus de 4 tentatives de vérification par numéro de téléphone par heure s'applique en amont. La réponse contient les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`. Remarque : les en-têtes `X-RateLimit-*`/`Retry-After` accompagnent uniquement l'erreur 429 de la limite d'écriture de 300/min ; l'erreur 429 du plafond par numéro ne comporte aucun en-tête de limitation de débit.",
            "content": {
              "application/json": {
                "examples": {
                  "Per-number cap": {
                    "summary": "Plus de 4 tentatives de vérification pour le même numéro au cours de la dernière heure",
                    "value": {
                      "detail": "Maximum verification attempts reached for this phone number. Only 4 authentication attempts are allowed per hour. Try again later or use a different number."
                    }
                  },
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Le fournisseur de vérification du téléphone est temporairement indisponible - une réponse 5xx, un délai d'attente dépassé ou une erreur de connexion persistante après les tentatives automatiques intégrées. Vous pouvez réessayer en toute sécurité ; le quota de tentatives n'est pas consommé.",
            "content": {
              "application/json": {
                "examples": {
                  "Provider outage": {
                    "summary": "Le fournisseur n'a pas répondu à la requête de vérification",
                    "value": {
                      "detail": "Phone verification is temporarily unavailable. Please try again shortly.",
                      "code": "phone_provider_unavailable"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Échec inattendu lors de la vérification du code en amont ne correspondant pas à une panne connue du fournisseur. Peut être réessayé en toute sécurité ; le quota de tentatives n'est consommé que par les vérifications terminées.",
            "content": {
              "application/json": {
                "examples": {
                  "Provider error": {
                    "summary": "La vérification du code n'a pas pu être effectuée",
                    "value": {
                      "detail": "Error checking phone verification"
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/bank/account-check/": {
      "post": {
        "summary": "Vérifier un compte bancaire",
        "description": "Vérifiez qu'un compte bancaire appartient bien à la personne ou à l'entreprise que vous indiquez, avant d'y envoyer des fonds. Aucune session ni connexion : envoyez le nom et le compte, lisez le résultat. Il s'agit de la [vérification de compte](/fr/core-technology/bank-verification/account-check) de l'étape Bank Verification, exécutée depuis votre backend.\n\n**Ce que vous envoyez.** Le `country` du compte (ISO 3166-1 alpha-3), le numéro de `account` tel que ce pays l'écrit, et le nom du titulaire (`holder`) : `full_name` pour une personne physique ou `business_name` pour une entreprise. Un nom d'entreprise permet de vérifier un compte professionnel.\n\n**Ce que vous recevez.** Le champ `result` vaut `match`, `close_match`, `no_match` ou `cannot_verify`. Lors d'un `close_match`, `holder_name` est le nom sous lequel la banque détient le compte, si la banque l'a renvoyé. Le champ `account` est renvoyé masqué, à l'exception de ses 4 derniers caractères.\n\n**Facturation.** Chaque vérification à laquelle la banque répond est facturée une fois au tarif de vérification de compte du pays du compte, quel que soit le résultat : un `no_match`, un compte inexistant et un `cannot_verify` sont également facturés. Une requête ayant renvoyé une erreur n'est jamais facturée.\n\n**Chaque requête constitue une nouvelle vérification.** Il n'y a pas de clé d'idempotence ni d'endpoint permettant de relire une vérification passée ; par conséquent, une requête réessayée est exécutée et facturée à nouveau. Enregistrez la réponse.\n\n**Sandbox.** Utilisez une clé API sandbox avec les coordonnées de compte fictives fournies. Une clé sandbox n'appelle aucune banque et n'est pas facturée. Les 4 derniers caractères de l'IBAN (ou à défaut, du numéro de compte) déterminent la réponse : `0001` un `close_match` avec un `holder_name`, `0002` un `close_match` sans celui-ci, `0003` et `0006` un `no_match`, `0004` `cannot_verify`, `0005` une erreur `503` et `0009` une erreur `400`. Toute autre fin de chaîne donne un `match`.\n\n**Clés API.** Une clé API avec restrictions de portée nécessite un accès en écriture aux sessions.",
        "operationId": "post_v3_bank_account_check",
        "tags": [
          "Standalone APIs"
        ],
        "x-didit-sdk": {
          "resource": "bank",
          "method": "account_check",
          "auth": "api_key",
          "server": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BankAccountCheckRequest"
              },
              "examples": {
                "Person, Nigeria": {
                  "summary": "Un code bancaire et un numéro de compte, vérifiés par rapport au nom d'une personne",
                  "value": {
                    "country": "NGA",
                    "account": {
                      "bank_code": "000014",
                      "account_number": "0123450001"
                    },
                    "holder": {
                      "full_name": "Maria Oliveira"
                    },
                    "vendor_data": "payout_20481"
                  }
                },
                "Company, Nigeria": {
                  "summary": "Un code bancaire et un numéro de compte, vérifiés par rapport au nom d'une entreprise",
                  "value": {
                    "country": "NGA",
                    "account": {
                      "bank_code": "000014",
                      "account_number": "0123456789"
                    },
                    "holder": {
                      "business_name": "Northwind Trading Ltd"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "La banque a répondu. La vérification est facturée, quel que soit le résultat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BankAccountCheckResponse"
                },
                "examples": {
                  "Close match": {
                    "summary": "La banque détient le compte sous un nom proche",
                    "value": {
                      "request_id": "c2f4a9e0-7b1d-4c3a-9e55-1d0a6b8f2a47",
                      "result": "close_match",
                      "holder_name": "MARIA R OLIVEIRA",
                      "account": "****0001",
                      "vendor_data": "payout_20481",
                      "created_at": "2026-10-21T14:32:08Z"
                    }
                  },
                  "Match": {
                    "summary": "La banque détient le compte sous le nom envoyé",
                    "value": {
                      "request_id": "5b0e2d7c-41a8-4f6e-9c3b-8e7d1a2f6c90",
                      "result": "match",
                      "holder_name": null,
                      "account": "****6789",
                      "vendor_data": null,
                      "created_at": "2026-10-21T14:35:41Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Refusé tel quel, et non facturé. `field` indique le champ du corps à corriger et `reason` en précise la raison, avec les mêmes motifs que ceux affichés dans le formulaire de compte hébergé. Seul le premier champ refusé est signalé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BankAccountCheckError"
                },
                "examples": {
                  "Missing field": {
                    "summary": "La vérification pour ce pays nécessite un code bancaire",
                    "value": {
                      "detail": "The bank code is not valid (required).",
                      "code": "invalid_account_input",
                      "field": "account.bank_code",
                      "reason": "required"
                    }
                  },
                  "Invalid IBAN": {
                    "summary": "L'IBAN n'a pas la bonne longueur pour son pays",
                    "value": {
                      "detail": "The iban is not valid (length).",
                      "code": "invalid_account_input",
                      "field": "account.iban",
                      "reason": "length"
                    }
                  },
                  "Refused by the bank": {
                    "summary": "La banque a refusé le compte tel qu'envoyé",
                    "value": {
                      "detail": "The account was refused as typed (rejected).",
                      "code": "invalid_account_input",
                      "field": "account.account_number",
                      "reason": "rejected"
                    }
                  },
                  "No name": {
                    "summary": "`holder` ne comporte ni `full_name` ni `business_name`",
                    "value": {
                      "detail": "Send full_name for a person or business_name for a company.",
                      "code": "invalid_account_input",
                      "field": "holder",
                      "reason": "required"
                    }
                  },
                  "Consent required": {
                    "summary": "La vérification du compte pour ce pays nécessite le consentement du titulaire du compte",
                    "value": {
                      "detail": "Account checks in this country need the account holder's explicit consent. Ask for it, then send `consent=true`.",
                      "code": "invalid_account_input",
                      "field": "consent",
                      "reason": "required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BankAccountCheckError"
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "La vérification ne peut pas être payée, elle n'a donc pas été exécutée. Rechargez votre solde, puis renvoyez-la.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BankAccountCheckError"
                },
                "examples": {
                  "Out of credit": {
                    "summary": "Votre solde ne permet pas de couvrir une vérification",
                    "value": {
                      "detail": "You don't have enough credits to perform this request. Please top up at https://business.didit.me",
                      "code": "insufficient_credits"
                    }
                  },
                  "Not in your contract": {
                    "summary": "Votre contrat ne prévoit aucun tarif pour l'API Account check",
                    "value": {
                      "detail": "Your contract does not price the Account check API. Contact your account manager.",
                      "code": "contract_rate_missing"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` ou le bearer token est manquant ou invalide, la requête provient d'une adresse hors de la liste d'adresses IP de la clé, ou une clé restreinte n'a pas d'accès en écriture aux sessions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BankAccountCheckError"
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucune clé API ou token valide",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "No sessions write": {
                    "summary": "Une clé restreinte sans accès en écriture aux sessions",
                    "value": {
                      "detail": "This API key has no write access to sessions."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune vérification de compte ne prend encore en charge ce compte, donc rien n'a été vérifié ni facturé. `country_not_covered` : aucune ne prend en charge son pays, ou son type de compte (personne physique ou entreprise) dans ce pays. `bank_not_covered` : aucune ne prend en charge sa banque.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BankAccountCheckError"
                },
                "examples": {
                  "Country not covered": {
                    "summary": "Aucune vérification de compte ne prend en charge le pays",
                    "value": {
                      "detail": "No account check serves this country yet.",
                      "code": "country_not_covered"
                    }
                  },
                  "Bank not covered": {
                    "summary": "Aucune vérification de compte ne prend en charge la banque du compte",
                    "value": {
                      "detail": "No account check serves this account's bank yet.",
                      "code": "bank_not_covered"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          },
          "503": {
            "description": "La banque n'a pas pu répondre. Rien n'a été vérifié ni facturé ; renvoyez la vérification plus tard.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BankAccountCheckError"
                },
                "examples": {
                  "Unavailable": {
                    "summary": "La banque n'a pas répondu",
                    "value": {
                      "detail": "The account check is temporarily unavailable and this request was not charged. Please try again.",
                      "code": "account_check_unavailable"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/bank/account-check/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"country\": \"NGA\",\n    \"account\": {\"bank_code\": \"000014\", \"account_number\": \"0123450001\"},\n    \"holder\": {\"full_name\": \"Maria Oliveira\"},\n    \"vendor_data\": \"payout_20481\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.bank.account_check(\n    country=\"NGA\",\n    account={\n        \"account_number\": \"0123450001\",\n        \"bank_code\": \"000014\",\n    },\n    holder={\n        \"full_name\": \"Maria Oliveira\",\n    },\n    vendor_data=\"payout_20481\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.bank.accountCheck({\n  country: \"NGA\",\n  account: {\n    account_number: \"0123450001\",\n    bank_code: \"000014\",\n  },\n  holder: {\n    full_name: \"Maria Oliveira\",\n  },\n  vendor_data: \"payout_20481\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Bank.AccountCheck(ctx, didit.BankAccountCheckRequest{\n\tCountry: \"NGA\",\n\tAccount: didit.BankAccountCheckRequestAccount{\n\t\tAccountNumber: didit.String(\"0123450001\"),\n\t\tBankCode:      didit.String(\"000014\"),\n\t},\n\tHolder: didit.BankAccountCheckHolder{\n\t\tFullName: didit.String(\"Maria Oliveira\"),\n\t},\n\tVendorData: didit.String(\"payout_20481\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.BankAccountCheckHolder;\nimport me.didit.types.BankAccountCheckPersonHolder;\nimport me.didit.types.BankAccountCheckRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.bank().accountCheck(BankAccountCheckRequest.builder()\n        .country(\"NGA\")\n        .account(BankAccountCheckRequest.Account.builder()\n                .accountNumber(\"0123450001\")\n                .bankCode(\"000014\")\n                .build())\n        .holder(BankAccountCheckHolder.ofBankAccountCheckPersonHolder(BankAccountCheckPersonHolder.builder()\n                .fullName(\"Maria Oliveira\")\n                .build()))\n        .vendorData(\"payout_20481\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->bank->accountCheck([\n    'country' => 'NGA',\n    'account' => [\n        'account_number' => '0123450001',\n        'bank_code' => '000014',\n    ],\n    'holder' => [\n        'full_name' => 'Maria Oliveira',\n    ],\n    'vendor_data' => 'payout_20481',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.bank.account_check(\n  country: \"NGA\",\n  account: {\n    account_number: \"0123450001\",\n    bank_code: \"000014\",\n  },\n  holder: {\n    full_name: \"Maria Oliveira\",\n  },\n  vendor_data: \"payout_20481\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Bank.AccountCheckAsync(new BankAccountCheckRequest\n{\n    Country = \"NGA\",\n    Account = new()\n    {\n        AccountNumber = \"0123450001\",\n        BankCode = \"000014\",\n    },\n    Holder = new()\n    {\n        FullName = \"Maria Oliveira\",\n    },\n    VendorData = \"payout_20481\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/email/send/": {
      "post": {
        "summary": "Envoyer le code par e-mail",
        "description": "Envoyez un code à usage unique (OTP) à une adresse e-mail, puis vérifiez-le avec [`POST /v3/email/check/`](/fr/standalone-apis/email-check).\n\n**Association entre l'envoi et la vérification.** L'état de la vérification est indexé par votre application et l'adresse `email` — l'appel de vérification ne prend pas de `request_id`. Chaque nouvel envoi crée une vérification en attente qui reste active pendant **5 minutes** : appelez la vérification avec la même adresse et le code reçu par l'utilisateur avant la fin du délai. Appeler à nouveau l'envoi pour la même adresse alors qu'une vérification est en attente génère un nouveau code pour cette même vérification (`status: \"Retry\"`, même `request_id`) ; le code précédent cesse de fonctionner. Au maximum une nouvelle tentative est associée de cette façon (deux envois au total) ; un envoi supplémentaire démarre une nouvelle vérification avec un nouveau `request_id`. La fenêtre de 5 minutes est mesurée à partir du premier envoi et n'est pas prolongée par les nouvelles tentatives.\n\n**Pré-vérification de délivrabilité.** Avant tout envoi, l'adresse fait l'objet d'une validation syntaxique et DNS/MX. Les adresses qui ne peuvent pas recevoir d'e-mails renvoient `200` avec `status: \"Undeliverable\"` et `reason: \"email_can_not_be_delivered\"` — aucun e-mail n'est envoyé, rien n'est facturé et la vérification est immédiatement finalisée comme `Declined` (une vérification ultérieure renvoie `Expired or Not Found`). Un envoi qui échoue pour une raison non liée à l'adresse (l'e-mail n'a pas pu être transmis pour livraison) renvoie `503` à la place : aucun code n'est envoyé, rien n'est facturé, la vérification reste ouverte et la même requête peut être réitérée.\n\n**Format du code et personnalisation.** Les codes comportent de 4 à 8 caractères (`options.code_size`, 6 par défaut), numériques par défaut ; définissez `options.alphanumeric_code: true` pour des lettres majuscules et des chiffres (la comparaison lors de la vérification est insensible à la casse). Le modèle d'e-mail est localisé via `options.locale` (54 langues prises en charge) et peut utiliser la personnalisation en marque blanche de votre application via `options.use_white_label_customization`.\n\n**Facturation.** Un crédit d'API de Vérification de l'e-mail par envoi réussi (`status: \"Success\"`), débité au moment de l'envoi. Les envois `Retry` et `Undeliverable` sont gratuits, et les vérifications sont gratuites.\n\n**Persistance des sessions.** Chaque nouvelle vérification est conservée sous la forme d'une session de type API : `request_id` est un véritable identifiant de session que vous pouvez transmettre à `GET /v3/session/{sessionId}/decision/`, la vérification apparaît dans la Business Console et les webhooks `status.updated` se déclenchent au fur et à mesure de sa progression.\n\n**Sandbox.** Les clés API sandbox ignorent la livraison et la facturation : après la validation de la requête (une entrée malformée renvoie toujours `400`), l'endpoint renvoie un payload statique `Success` avec un `request_id` aléatoire ; aucun e-mail n'est envoyé et rien n'est conservé. Utilisez le code `123456` lors de la vérification en sandbox.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou invalides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) — cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes/min par clé API sur l'ensemble des endpoints POST/PATCH/DELETE ; tout dépassement renvoie `429`.",
        "operationId": "post_v3email_send",
        "x-didit-sdk": {
          "resource": "email",
          "method": "send_code",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/email/send/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"email\": \"alice@example.com\",\n    \"options\": { \"code_size\": 6, \"locale\": \"en\" },\n    \"vendor_data\": \"user-1234\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.email.send_code(\n    email=\"alice@example.com\",\n    options={\n        \"locale\": \"en\",\n    },\n    vendor_data=\"user-1234\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.email.sendCode({\n  email: \"alice@example.com\",\n  options: {\n    locale: \"en\",\n  },\n  vendor_data: \"user-1234\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Email.SendCode(ctx, didit.EmailSendCodeParams{\n\tEmail: \"alice@example.com\",\n\tOptions: didit.Some(didit.EmailSendCodeParamsOptions{\n\t\tLocale: didit.Some(didit.EmailSendCodeParamsOptionsLocale(\"en\")),\n\t}),\n\tVendorData: didit.String(\"user-1234\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.EmailSendCodeParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.email().sendCode(EmailSendCodeParams.builder()\n        .email(\"alice@example.com\")\n        .options(EmailSendCodeParams.Options.builder()\n                .locale(EmailSendCodeParams.Options.Locale.of(\"en\"))\n                .build())\n        .vendorData(\"user-1234\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->email->sendCode([\n    'email' => 'alice@example.com',\n    'options' => [\n        'locale' => 'en',\n    ],\n    'vendor_data' => 'user-1234',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.email.send_code(\n  email: \"alice@example.com\",\n  options: {\n    locale: \"en\",\n  },\n  vendor_data: \"user-1234\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Email.SendCodeAsync(new EmailSendCodeParams\n{\n    Email = \"alice@example.com\",\n    Options = new EmailSendCodeParamsOptions\n    {\n        Locale = new EmailSendCodeParamsOptionsLocale(\"en\"),\n    },\n    VendorData = \"user-1234\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Adresse e-mail du destinataire. Les adresses malformées renvoient `400` ; les adresses syntaxiquement valides mais incapables de recevoir des e-mails (échec de validation DNS/MX) renvoient `200` avec `status: \"Undeliverable\"`.",
                    "example": "alice@example.com"
                  },
                  "options": {
                    "type": "object",
                    "description": "Options de format, de localisation et d'image de marque de l'OTP. Tous les champs sont facultatifs.",
                    "properties": {
                      "code_size": {
                        "type": "integer",
                        "minimum": 4,
                        "maximum": 8,
                        "default": 6,
                        "description": "Nombre de caractères dans l'OTP (chiffres par défaut ; lettres majuscules et chiffres lorsque `alphanumeric_code` est `true`)."
                      },
                      "alphanumeric_code": {
                        "type": "boolean",
                        "default": false,
                        "description": "Lorsque la valeur est `true`, l'OTP est composé de lettres majuscules `A–Z` et de chiffres `0–9` au lieu de chiffres uniquement. La comparaison effectuée par `/v3/email/check/` est insensible à la casse."
                      },
                      "locale": {
                        "type": "string",
                        "maxLength": 5,
                        "enum": [
                          "en",
                          "ar",
                          "bn",
                          "bg",
                          "bs",
                          "ca",
                          "cs",
                          "da",
                          "de",
                          "el",
                          "es",
                          "et",
                          "fa",
                          "fi",
                          "fr",
                          "he",
                          "hi",
                          "hr",
                          "hu",
                          "hy",
                          "id",
                          "it",
                          "ja",
                          "ka",
                          "kk",
                          "ko",
                          "ky",
                          "lt",
                          "lv",
                          "cnr",
                          "mk",
                          "mn",
                          "ms",
                          "nl",
                          "no",
                          "pl",
                          "pt-BR",
                          "pt",
                          "ro",
                          "ru",
                          "sk",
                          "sl",
                          "so",
                          "sq",
                          "sr",
                          "sv",
                          "th",
                          "tr",
                          "uk",
                          "uz",
                          "vi",
                          "zh-CN",
                          "zh-TW",
                          "zh"
                        ],
                        "description": "Langue du modèle d'e-mail OTP. La valeur par défaut est `en`. Les valeurs non prises en charge renvoient une erreur `400` listant toutes les langues acceptées.",
                        "example": "en"
                      },
                      "use_white_label_customization": {
                        "type": "boolean",
                        "default": false,
                        "description": "Lorsque la valeur est `true`, l'e-mail OTP utilise la personnalisation en marque blanche de votre application (logo, couleurs, image de marque de l'expéditeur) au lieu du modèle Didit par défaut."
                      }
                    }
                  },
                  "signals": {
                    "type": "object",
                    "description": "Signaux d'appareil et de réseau optionnels concernant l'utilisateur final, transmis à la couche antifraude pour améliorer la détection de trafic abusif ou automatisé. Tous les champs sont optionnels.",
                    "properties": {
                      "ip": {
                        "type": "string",
                        "description": "Adresse de l'appareil de l'utilisateur final. IPv4 ou IPv6.",
                        "example": "192.0.2.1"
                      },
                      "device_id": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Identifiant unique de l'appareil de l'utilisateur final. Android : `ANDROID_ID` ; iOS : `identifierForVendor`.",
                        "example": "8F0B8FDD-C2CB-4387-B20A-56E9B2E5A0D2"
                      },
                      "device_platform": {
                        "type": "string",
                        "enum": [
                          "android",
                          "ios",
                          "ipados",
                          "tvos",
                          "web"
                        ],
                        "description": "Plateforme de l'appareil de l'utilisateur final."
                      },
                      "device_model": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Modèle de l'appareil de l'utilisateur final.",
                        "example": "iPhone17,2"
                      },
                      "os_version": {
                        "type": "string",
                        "maxLength": 64,
                        "description": "Version du système d'exploitation de l'appareil de l'utilisateur final.",
                        "example": "18.0.1"
                      },
                      "app_version": {
                        "type": "string",
                        "maxLength": 64,
                        "description": "Version de votre application.",
                        "example": "1.2.34"
                      },
                      "user_agent": {
                        "type": "string",
                        "maxLength": 512,
                        "description": "Agent utilisateur du navigateur ou de l'application de l'utilisateur final.",
                        "example": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1"
                      }
                    }
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Identifiant optionnel contrôlé par l'appelant (votre identifiant utilisateur interne, un e-mail, un UUID, etc.) persisté sur la session et renvoyé dans la réponse d'envoi, la réponse de vérification de correspondance, les webhooks et la Business Console. Utilisez-le pour corréler le `request_id` de Didit avec votre dossier utilisateur."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "Objet JSON libre optionnel conservé sur la session et renvoyé dans la réponse d'envoi, la réponse de vérification de correspondance, les webhooks et la Business Console."
                  }
                },
                "required": [
                  "email"
                ]
              },
              "examples": {
                "Numeric 6-digit code": {
                  "summary": "Par défaut — code numérique à 6 chiffres en anglais",
                  "value": {
                    "email": "alice@example.com",
                    "options": {
                      "locale": "en"
                    },
                    "vendor_data": "user-1234"
                  }
                },
                "Alphanumeric 8-character code": {
                  "summary": "Lettres majuscules + chiffres, modèle espagnol",
                  "value": {
                    "email": "bob@example.com",
                    "options": {
                      "code_size": 8,
                      "alphanumeric_code": true,
                      "locale": "es"
                    }
                  }
                },
                "White-label branding": {
                  "summary": "Envoyez l'e-mail contenant l'OTP avec la personnalisation en marque blanche de votre application",
                  "value": {
                    "email": "carol@example.com",
                    "options": {
                      "locale": "en",
                      "use_white_label_customization": true
                    },
                    "vendor_data": "user-5678"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Envoi pris en compte. Examinez `status` : `Success` et `Retry` indiquent qu'un code est en cours d'envoi ; `Undeliverable` signifie que l'adresse ne peut pas recevoir d'e-mails et que la vérification est déjà finalisée en tant que `Declined`. `request_id` est l'identifiant de session persistant (même identifiant lors d'un `Retry`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailVerificationSendResponse"
                },
                "examples": {
                  "Success": {
                    "summary": "OTP envoyé par e-mail pour une nouvelle vérification (facturé)",
                    "value": {
                      "request_id": "e39cb057-92fc-4b59-b84e-02fec29a0f24",
                      "status": "Success",
                      "reason": null,
                      "vendor_data": "user-1234",
                      "metadata": null
                    }
                  },
                  "Retry": {
                    "summary": "Deuxième envoi dans la fenêtre de 5 minutes — nouveau code, même request_id, gratuit",
                    "value": {
                      "request_id": "e39cb057-92fc-4b59-b84e-02fec29a0f24",
                      "status": "Retry",
                      "reason": null,
                      "vendor_data": "user-1234",
                      "metadata": null
                    }
                  },
                  "Undeliverable": {
                    "summary": "Échec de la validation DNS/MX de l'adresse — vérification finalisée avec le statut Refusé, aucune facturation",
                    "value": {
                      "request_id": "cb1a5011-344d-444d-bdce-218904745d7f",
                      "status": "Undeliverable",
                      "reason": "email_can_not_be_delivered",
                      "vendor_data": "user-1234",
                      "metadata": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — enveloppe d'erreur de champ de DRF : un tableau de messages par champ concerné, imbriqué sous `options` pour les erreurs d'options.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid email": {
                    "summary": "Adresse e-mail mal formée",
                    "value": {
                      "email": [
                        "Enter a valid email address."
                      ]
                    }
                  },
                  "Unsupported locale": {
                    "summary": "`options.locale` en dehors de l'ensemble pris en charge",
                    "value": {
                      "options": {
                        "locale": [
                          "Invalid locale. Supported locales are en, ar, bn, bg, bs, ca, cs, da, de, el, es, et, fa, fi, fr, he, hi, hr, hu, hy, id, it, ja, ka, kk, ko, ky, lt, lv, cnr, mk, mn, ms, nl, no, pl, pt-BR, pt, ro, ru, sk, sl, so, sq, sr, sv, th, tr, uk, uz, vi, zh-CN, zh-TW, zh."
                        ]
                      }
                    }
                  },
                  "Code size out of range": {
                    "summary": "`options.code_size` en dehors de la plage 4–8",
                    "value": {
                      "options": {
                        "code_size": [
                          "Ensure this value is less than or equal to 8."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant (`{\"detail\": ...}`) ; une clé incorrecte, révoquée ou expirée renvoie `401`. Également renvoyé avant tout envoi lorsque le solde de l'organisation ne permet pas de couvrir un crédit de l'API Vérification de l'e-mail (`{\"error\": ...}`).",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir le prix d'envoi",
                    "value": {
                      "error": "You don't have enough credits to perform this request."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "L'e-mail n'a pas pu être envoyé pour une raison indépendante de l'adresse (le fournisseur de messagerie n'a pas pu être joint, a dépassé le délai d'attente ou a refusé lui-même l'envoi) : aucun code n'a donc été envoyé et rien n'a été facturé ni comptabilisé comme tentative d'envoi. Réessayez la même requête.",
            "content": {
              "application/json": {
                "examples": {
                  "Email delivery unavailable": {
                    "summary": "Le fournisseur d'e-mail a échoué après une tentative automatique",
                    "value": {
                      "detail": "Email delivery is temporarily unavailable. Please try again."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/email/check/": {
      "post": {
        "summary": "Vérifier le code e-mail",
        "description": "Vérifiez l'OTP envoyé par [`POST /v3/email/send/`](/fr/standalone-apis/email-send) et obtenez le résultat final de la vérification ainsi que des informations sur l'e-mail : délivrabilité, exposition aux fuites de données (`is_breached` et la liste `breaches` provenant d'une base de données d'intelligence sur les fuites), détection de fournisseurs jetables et utilisation en doublon de l'adresse sur vos sessions.\n\n**Comment la vérification identifie l'envoi.** La correspondance s'effectue par votre application et l'adresse `email` ; `request_id` n'est pas un paramètre d'entrée. La vérification en attente la plus récente créée au cours des **5 dernières minutes** est contrôlée. S'il n'en existe aucune (jamais envoyée, déjà finalisée, non distribuable au moment de l'envoi ou datant de plus de 5 minutes), l'endpoint renvoie `200` avec `status: \"Expired or Not Found\"`.\n\n**Quota de tentatives.** Chaque vérification autorise **3 tentatives de code**. Les deux premiers codes incorrects renvoient `status: \"Failed\"` avec le nombre de tentatives restantes et `email: null` ; le troisième code incorrect finalise la vérification en `Declined` avec un avertissement `EMAIL_CODE_ATTEMPTS_EXCEEDED` et renvoie le rapport complet de l'e-mail. Les codes sont comparés sans distinction de casse (pertinent pour les envois d'`alphanumeric_code`) ; seul le code envoyé le plus récemment est valide.\n\n**Résultats.** `Approved` : code correct et aucun risque entraînant un refus. `Declined` (définitif) : le code était correct mais un risque entraînant un refus correspondait (une action `DECLINE` ci-dessous, une adresse sur liste de blocage ou une adresse détectée comme non distribuable lors de la finalisation), ou le quota de tentatives a été épuisé. `Failed` : code incorrect, tentatives restantes. `Expired or Not Found` : rien à vérifier. Pour `Approved`/`Declined`, l'`request_id` est égal au `request_id` de l'envoi (l'identifiant de session) et `email` contient le rapport complet (`is_breached`, `breaches`, `is_disposable`, `is_undeliverable`, `warnings`, `lifecycle`, `matches`) ; pour `Failed` et `Expired or Not Found`, l'`request_id` est un UUID aléatoire à usage unique.\n\n**Actions de risque.** `duplicated_email_action`, `breached_email_action` et `disposable_email_action` déterminent ce qui se passe lorsque le risque correspondant est détecté sur un code correct : `DECLINE` bascule le statut final à `Declined` ; `NO_ACTION` (par défaut) consigne le risque dans `email.warnings` sans impacter le statut.\n\n**Facturation.** Les vérifications sont gratuites : le crédit est consommé par l'envoi réussi.\n\n**Persistance de session.** Une vérification finalisée met à jour la session créée par l'envoi (visible dans la Business Console, consultable via `GET /v3/session/{sessionId}/decision/`) et déclenche un webhook `status.updated`.\n\n**Sandbox.** Les clés API sandbox ignorent tout traitement : tout code bien formé (y compris `123456`) renvoie un payload statique `Approved` avec un objet `email` simplifié (`status`, `email`, `is_breached`, `is_disposable`, `is_undeliverable`) ; une entrée mal formée renvoie toujours `400`. Rien n'est conservé.\n\n**Authentification.** Envoyez la clé API de votre application dans l'en-tête `x-api-key`. Des identifiants manquants ou invalides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) ; cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Quota partagé d'écriture de 300 requêtes/min par clé API sur l'ensemble des endpoints POST/PATCH/DELETE ; son dépassement renvoie `429`.\n\n**Empreinte sociale.** Définissez `enable_social` sur `true` pour ajouter un bloc `email_social` : les plateformes en ligne sur lesquelles cette adresse est inscrite, avec les décomptes par catégorie et les détails de profil disponibles. `profiles_registered: 0` signifie que les plateformes ont été vérifiées et que l'adresse n'a été trouvée sur aucune d'elles - une réponse valide et facturable. Le bloc est absent lorsque le module complémentaire n'a pas été demandé ou que la vérification n'a pas pu aboutir, et il n'est pas facturé dans ce cas. La facturation ajoute une unité `email_social` par requête en plus du prix propre à cet endpoint.",
        "operationId": "post_v3email_check",
        "x-didit-sdk": {
          "resource": "email",
          "method": "check_code",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/email/check/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"email\": \"alice@example.com\",\n    \"code\": \"123456\",\n    \"disposable_email_action\": \"DECLINE\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.email.check_code(\n    email=\"alice@example.com\",\n    code=\"123456\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.email.checkCode({\n  email: \"alice@example.com\",\n  code: \"123456\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Email.CheckCode(ctx, didit.EmailCheckCodeParams{\n\tEmail: \"alice@example.com\",\n\tCode:  \"123456\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.EmailCheckCodeParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.email().checkCode(EmailCheckCodeParams.builder()\n        .email(\"alice@example.com\")\n        .code(\"123456\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->email->checkCode([\n    'email' => 'alice@example.com',\n    'code' => '123456',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.email.check_code(\n  email: \"alice@example.com\",\n  code: \"123456\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Email.CheckCodeAsync(new EmailCheckCodeParams\n{\n    Email = \"alice@example.com\",\n    Code = \"123456\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "La même adresse e-mail que celle utilisée dans l'appel [`POST /v3/email/send/`](/fr/standalone-apis/email-send) correspondant. C'est ce qui associe la vérification à l'envoi.",
                    "example": "alice@example.com"
                  },
                  "code": {
                    "type": "string",
                    "maxLength": 10,
                    "description": "L'OTP reçu par l'utilisateur final : 4 à 8 chiffres, ou 4 à 8 lettres/chiffres lorsque `alphanumeric_code: true` a été utilisé lors de l'envoi. La comparaison est insensible à la casse.",
                    "example": "123456"
                  },
                  "duplicated_email_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Que faire lorsque la même adresse a déjà été utilisée et approuvée par un utilisateur différent (seules les vérifications précédemment approuvées comptent) (`vendor_data` distinct) de votre application. `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le risque dans `email.warnings` et renseigne `email.matches`."
                  },
                  "breached_email_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Ce qu'il faut faire lorsque l'adresse apparaît dans des violations de données connues (`email.is_breached`). `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le risque dans `email.warnings`."
                  },
                  "disposable_email_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Que faire lorsque le domaine appartient à un fournisseur d'adresses e-mail jetables/temporaires (`email.is_disposable`). `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le risque dans `email.warnings`."
                  },
                  "enable_enrichment": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lorsque la valeur est `true`, exécute également une analyse de renseignements sur l'adresse e-mail : un score de risque et son historique de fuites de données. Facturé comme une unité `email_intelligence_api` par requête ($0.05 au prix catalogue) en plus du prix propre à cet endpoint. La requête renvoie `403` lorsque votre solde ne permet pas de la couvrir.",
                    "example": false
                  },
                  "email_intelligence_score_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque le score de risque de l'intelligence e-mail est supérieur au seuil. `DECLINE` fait passer le `status` final à `Declined` ; `NO_ACTION` enregistre le signal sans refuser. Ne prend effet que lorsque `enable_enrichment` est `true`."
                  },
                  "recent_email_breach_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque l'adresse apparaît dans une fuite de données connue récente. `DECLINE` bascule le `status` final à `Declined` ; `NO_ACTION` enregistre le signal sans refuser. Ne prend effet que lorsque `enable_enrichment` est `true`."
                  },
                  "frequent_email_breach_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque l'adresse apparaît dans de nombreuses fuites de données connues. `DECLINE` bascule le `status` final à `Declined` ; `NO_ACTION` enregistre le signal sans refuser. Ne prend effet que lorsque `enable_enrichment` est `true`."
                  },
                  "enable_social": {
                    "type": "boolean",
                    "default": false,
                    "description": "Si true, recherche également l'empreinte sociale de l'adresse : les plateformes d'e-mail, sociales, professionnelles, d'e-commerce et de divertissement sur lesquelles elle est enregistrée. Facturé comme une unité `email_social` par requête en plus du prix propre à cet endpoint.",
                    "example": true
                  },
                  "email_no_social_presence_action": {
                    "type": "string",
                    "enum": [
                      "NO_ACTION",
                      "DECLINE"
                    ],
                    "default": "NO_ACTION",
                    "description": "Action lorsque la vérification de l'empreinte sociale ne trouve l'adresse enregistrée sur aucune des plateformes couvertes. Seuls NO_ACTION et DECLINE sont acceptés sur cet endpoint ; REVIEW est disponible sur la clé de configuration du workflow du même nom."
                  }
                },
                "required": [
                  "email",
                  "code"
                ]
              },
              "examples": {
                "Default": {
                  "summary": "Enregistrer tous les risques sans jamais refuser automatiquement",
                  "value": {
                    "email": "alice@example.com",
                    "code": "123456"
                  }
                },
                "Strict risk policy": {
                  "summary": "Refuser automatiquement les boîtes de réception jetables et compromises",
                  "value": {
                    "email": "alice@example.com",
                    "code": "123456",
                    "disposable_email_action": "DECLINE",
                    "breached_email_action": "DECLINE"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vérification terminée — les codes erronés et les vérifications manquantes renvoient également `200` ; inspectez `status`, et non le code HTTP. `email` n'est renseigné que pour les résultats finalisés (`Approved`/`Declined`), vaut `null` pour `Failed`, et est absent pour `Expired or Not Found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailVerificationCheckResponse"
                },
                "examples": {
                  "Approved": {
                    "summary": "Code correct — adresse propre, rapport d'e-mail complet",
                    "value": {
                      "request_id": "e39cb057-92fc-4b59-b84e-02fec29a0f24",
                      "status": "Approved",
                      "message": "The verification code is correct.",
                      "email": {
                        "status": "Approved",
                        "email": "alice@example.com",
                        "is_breached": false,
                        "breaches": [],
                        "is_disposable": false,
                        "is_undeliverable": false,
                        "verification_attempts": 1,
                        "verified_at": "2026-06-12T01:24:47.311323Z",
                        "warnings": [],
                        "lifecycle": [
                          {
                            "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
                            "timestamp": "2026-06-12T01:23:39.580554+00:00",
                            "details": {
                              "status": "Success",
                              "reason": null
                            },
                            "fee": 0.02
                          },
                          {
                            "type": "VALID_CODE_ENTERED",
                            "timestamp": "2026-06-12T01:24:47.311201+00:00",
                            "details": {
                              "code_tried": "123456",
                              "status": "Approved"
                            },
                            "fee": 0
                          },
                          {
                            "type": "EMAIL_VERIFICATION_APPROVED",
                            "timestamp": "2026-06-12T01:24:47.384292+00:00",
                            "details": null,
                            "fee": 0
                          }
                        ],
                        "matches": []
                      },
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:47.401719+00:00"
                    }
                  },
                  "Approved with breach exposure": {
                    "summary": "Code correct ; exposition à une fuite enregistrée comme avertissement (breached_email_action=NO_ACTION)",
                    "value": {
                      "request_id": "3a1f2b6c-9d4e-4f7a-8b2c-1e5d6f7a8b9c",
                      "status": "Approved",
                      "message": "The verification code is correct.",
                      "email": {
                        "status": "Approved",
                        "email": "bob@example.com",
                        "is_breached": true,
                        "breaches": [
                          {
                            "name": "ExampleApp",
                            "domain": "exampleapp.com",
                            "breach_date": "2019-03-21",
                            "breach_emails_count": 763117,
                            "description": "In March 2019, the social platform ExampleApp suffered a data breach that exposed email addresses and passwords.",
                            "logo_path": "https://<media-host>/logos/ExampleApp.png",
                            "data_classes": [
                              "email_addresses",
                              "passwords"
                            ],
                            "is_verified": true
                          }
                        ],
                        "is_disposable": false,
                        "is_undeliverable": false,
                        "verification_attempts": 1,
                        "verified_at": "2026-06-12T01:24:47.311323Z",
                        "warnings": [
                          {
                            "feature": "EMAIL",
                            "risk": "BREACHED_EMAIL_DETECTED",
                            "additional_data": null,
                            "log_type": "information",
                            "short_description": "Breached email detected",
                            "long_description": "This email address was found in one or more known data breaches."
                          }
                        ],
                        "lifecycle": [
                          {
                            "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
                            "timestamp": "2026-06-12T01:23:39.580554+00:00",
                            "details": {
                              "status": "Success",
                              "reason": null
                            },
                            "fee": 0.02
                          },
                          {
                            "type": "VALID_CODE_ENTERED",
                            "timestamp": "2026-06-12T01:24:47.311201+00:00",
                            "details": {
                              "code_tried": "835126",
                              "status": "Approved"
                            },
                            "fee": 0
                          },
                          {
                            "type": "EMAIL_VERIFICATION_APPROVED",
                            "timestamp": "2026-06-12T01:24:47.384292+00:00",
                            "details": null,
                            "fee": 0
                          }
                        ],
                        "matches": []
                      },
                      "vendor_data": "user-5678",
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:47.401719+00:00"
                    }
                  },
                  "Failed (attempts remaining)": {
                    "summary": "Code erroné — l'utilisateur peut réessayer ; request_id est ici un UUID à usage unique",
                    "value": {
                      "request_id": "11111111-2222-3333-4444-555555555555",
                      "status": "Failed",
                      "message": "The verification code is incorrect. Attempts remaining: 2",
                      "email": null,
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:21.512340+00:00"
                    }
                  },
                  "Declined (risk policy)": {
                    "summary": "Code correct, mais l'adresse est jetable et disposable_email_action=DECLINE",
                    "value": {
                      "request_id": "8c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
                      "status": "Declined",
                      "message": "The verification code is correct.",
                      "email": {
                        "status": "Declined",
                        "email": "tempuser42@mailinator.com",
                        "is_breached": false,
                        "breaches": [],
                        "is_disposable": true,
                        "is_undeliverable": false,
                        "verification_attempts": 1,
                        "verified_at": "2026-06-12T01:24:47.311323Z",
                        "warnings": [
                          {
                            "feature": "EMAIL",
                            "risk": "DISPOSABLE_EMAIL_DETECTED",
                            "additional_data": null,
                            "log_type": "error",
                            "short_description": "Disposable email detected",
                            "long_description": "The system detected that the email is disposable, which is not allowed."
                          }
                        ],
                        "lifecycle": [
                          {
                            "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
                            "timestamp": "2026-06-12T01:23:39.580554+00:00",
                            "details": {
                              "status": "Success",
                              "reason": null
                            },
                            "fee": 0.02
                          },
                          {
                            "type": "VALID_CODE_ENTERED",
                            "timestamp": "2026-06-12T01:24:47.311201+00:00",
                            "details": {
                              "code_tried": "123456",
                              "status": "Approved"
                            },
                            "fee": 0
                          },
                          {
                            "type": "EMAIL_VERIFICATION_DECLINED",
                            "timestamp": "2026-06-12T01:24:47.384292+00:00",
                            "details": {
                              "reason": "DISPOSABLE_EMAIL_DETECTED"
                            },
                            "fee": 0
                          }
                        ],
                        "matches": []
                      },
                      "vendor_data": "user-1234",
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:47.401719+00:00"
                    }
                  },
                  "Expired or Not Found": {
                    "summary": "Aucune vérification en attente pour cette adresse au cours des 5 dernières minutes",
                    "value": {
                      "request_id": "88808a77-06e9-4cb0-85f5-9c052ddfd987",
                      "status": "Expired or Not Found",
                      "message": "No pending email verification found in the last 5 minutes.",
                      "vendor_data": null,
                      "metadata": null,
                      "created_at": "2026-06-12T01:24:59.887904+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — enveloppe d'erreur de champ de DRF : un tableau de messages par champ concerné.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid email": {
                    "summary": "Adresse e-mail mal formée",
                    "value": {
                      "email": [
                        "Enter a valid email address."
                      ]
                    }
                  },
                  "Missing code": {
                    "summary": "`code` n'est pas inclus dans le corps",
                    "value": {
                      "code": [
                        "This field is required."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les vérifications sont gratuites, aucun contrôle de crédit n'est donc effectué ici.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/workflows/": {
      "get": {
        "summary": "Lister les workflows",
        "description": "Lister vos workflows, les plus récents en premier, dans une enveloppe de pagination limit/offset (`{count, next, previous, results}`, taille de page par défaut 50). Chaque ligne correspond à une version ; `workflow_id` est l'identifiant de groupe stable et les nouvelles sessions utilisent la dernière version `published`.",
        "operationId": "list_workflows",
        "x-didit-sdk": {
          "resource": "workflows",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Workflows"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            },
            "description": "Taille de page (nombre de workflows par page)."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Nombre de lignes à ignorer avant le premier workflow retourné."
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de workflows triés par `created_at` décroissant, encapsulée dans l'enveloppe de pagination. Chaque élément de `results` est un `WorkflowListItem`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre total de versions de workflow pour l'application."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WorkflowListItem"
                      }
                    }
                  }
                },
                "examples": {
                  "Two workflows": {
                    "summary": "Un workflow KYC par défaut et un brouillon de workflow KYC + AML",
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
                          "workflow_id": "a1b2c3d4-5678-90ab-cdef-111111111111",
                          "workflow_label": "Standard KYC",
                          "workflow_type": "kyc",
                          "is_default": true,
                          "is_archived": false,
                          "is_white_label_enabled": false,
                          "total_price": 0.15,
                          "min_price": 0.15,
                          "max_price": 0.15,
                          "features": "OCR + LIVENESS + FACE_MATCH",
                          "is_simple_workflow": true,
                          "is_editable": false,
                          "workflow_url": "https://verify.didit.me/u/_yljPOx8RWG3UAz5ZRQGVQ",
                          "max_retry_attempts": 3,
                          "retry_window_days": 7,
                          "session_expiration_time": 604800,
                          "version": 2,
                          "status": "published",
                          "has_draft": false,
                          "created_by": {
                            "name": "Alex Mateo",
                            "email": "alex@example.com",
                            "type": "user"
                          },
                          "updated_at": "2026-04-12T10:30:00Z"
                        },
                        {
                          "uuid": "b2c3d4e5-6789-01bc-defa-222222222222",
                          "workflow_id": "b2c3d4e5-6789-01bc-defa-222222222222",
                          "workflow_label": "Full Verification + AML",
                          "workflow_type": "kyc",
                          "is_default": false,
                          "is_archived": false,
                          "is_white_label_enabled": false,
                          "total_price": 0.25,
                          "min_price": 0.25,
                          "max_price": 0.25,
                          "features": "OCR + LIVENESS + FACE_MATCH + AML",
                          "is_simple_workflow": true,
                          "is_editable": true,
                          "workflow_url": "https://verify.didit.me/u/Aq3kPOx8RWG3UAz5ZRQGVQ",
                          "max_retry_attempts": 3,
                          "retry_window_days": 7,
                          "session_expiration_time": 604800,
                          "version": 1,
                          "status": "draft",
                          "has_draft": true,
                          "created_by": null,
                          "updated_at": "2026-04-15T18:05:21Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé API est manquante, malformée, expirée ou appartient à une autre application. Corps : `{\"detail\": \"You do not have permission to perform this action.\"}`. Actualisez le token via l'[API Auth](/fr/auth-api/get-credentials) et réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle et respectez tout en-tête `Retry-After`."
          },
          "500": {
            "description": "Erreur serveur inattendue lors de la construction de la liste. La requête peut être réessayée en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X GET 'https://verification.didit.me/v3/workflows/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Accept: application/json'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.workflows.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.workflows.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Workflows.ListAutoPaging(ctx, didit.WorkflowsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.workflows().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->workflows->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.workflows.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Workflows.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "summary": "Créer un workflow",
        "description": "Créez un workflow simple. Envoyez `features` dans l'ordre d'exécution (des règles d'ordonnancement s'appliquent) ; défini par défaut sur `published` v1. Le corps accepte UNIQUEMENT les champs répertoriés dans `SimpleWorkflowRequest` — toute autre clé (y compris `workflow_type`) est rejetée avec une erreur 400. Non idempotent — chaque appel crée un nouveau workflow. Un maximum de 50 workflows par application.",
        "operationId": "create_workflow",
        "x-didit-sdk": {
          "resource": "workflows",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Workflows"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimpleWorkflowRequest"
              },
              "examples": {
                "Simple KYC": {
                  "summary": "Workflow linéaire de vérification d'identité, de détection du vivant et de correspondance faciale",
                  "value": {
                    "workflow_label": "Standard KYC",
                    "features": [
                      {
                        "feature": "OCR",
                        "config": {
                          "duplicated_user_action": "review"
                        }
                      },
                      {
                        "feature": "LIVENESS",
                        "config": {
                          "face_liveness_method": "passive"
                        }
                      },
                      {
                        "feature": "FACE_MATCH",
                        "config": {
                          "face_match_score_decline_threshold": 40,
                          "face_match_score_review_threshold": 60
                        }
                      }
                    ]
                  }
                },
                "KYC + AML": {
                  "summary": "Exécuter le filtrage AML après la vérification d'identité",
                  "value": {
                    "workflow_label": "KYC with AML",
                    "features": [
                      {
                        "feature": "OCR"
                      },
                      {
                        "feature": "AML",
                        "config": {
                          "aml_score_review_threshold": 70,
                          "aml_score_approve_threshold": 30
                        }
                      }
                    ]
                  }
                },
                "Questionnaire workflow": {
                  "summary": "Exécuter un questionnaire créé avec POST /v3/questionnaires/",
                  "value": {
                    "workflow_label": "Source of Funds",
                    "features": [
                      {
                        "feature": "QUESTIONNAIRE",
                        "config": {
                          "questionnaire_uuid": "11111111-2222-3333-4444-555555555555",
                          "review_questionnaire_manually": true
                        }
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Workflow créé. Le corps de la réponse contient la configuration COMPLÈTE du workflow — la même sérialisation brute `VerificationSettings` renvoyée par `GET /v3/workflows/{settings_uuid}/` (~190 champs : chaque activation de fonctionnalité, seuil, action et le `workflow_graph` généré), et non l'élément de liste compact. Enregistrez l'`uuid` (également exposé sous le nom `workflow_id`) afin de pouvoir le référencer lors de futurs appels de création de session. Remarque : `features` est une chaîne jointe par `\" + \"` et les prix sont des nombres JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowDetail"
                },
                "examples": {
                  "Created (abbreviated)": {
                    "summary": "Champs clés de l'objet de configuration complet",
                    "value": {
                      "uuid": "c3d4e5f6-7890-12cd-ef34-333333333333",
                      "workflow_id": "c3d4e5f6-7890-12cd-ef34-333333333333",
                      "workflow_label": "Standard KYC",
                      "workflow_type": null,
                      "is_default": false,
                      "is_archived": false,
                      "total_price": 0.15,
                      "min_price": 0.15,
                      "max_price": 0.15,
                      "features": "OCR + LIVENESS + FACE_MATCH",
                      "is_simple_workflow": false,
                      "is_editable": false,
                      "workflow_url": "https://verify.didit.me/u/w9TkPOx8RWG3UAz5ZRQGVQ",
                      "workflow_graph": {
                        "start_node": "ocr",
                        "nodes": "... one node per feature plus a final status node ..."
                      },
                      "max_retry_attempts": 3,
                      "retry_window_days": 7,
                      "session_expiration_time": 604800,
                      "version": 1,
                      "status": "published",
                      "published_at": "2026-05-17T10:30:00Z",
                      "created_at": "2026-05-17T10:30:00Z",
                      "updated_at": "2026-05-17T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Causes courantes : une clé de premier niveau en dehors de la liste autorisée (par exemple `workflow_type`), une valeur de `feature` inconnue, une fonctionnalité placée avant sa dépendance (par exemple `FACE_MATCH` avant `OCR`), une fonctionnalité passive (`AML`, `IP_ANALYSIS`, `DATABASE_VALIDATION`, `KYB_KEY_PEOPLE`) utilisée comme première étape, une fonctionnalité `QUESTIONNAIRE` dont le `config.questionnaire_uuid` n'existe pas pour cette application, une fonctionnalité `SIGNATURE` qui passerait en production sans document à signer, une fonctionnalité `SIGNATURE` avec `signature_level: \"aes\"` alors que le niveau avancé (AES) n'est pas disponible (`aes_not_available`, voir `signature_availability` sur le workflow), ou un seuil hors limites. Le corps est un objet d'erreur de validation DRF — les clés sont des noms de champs, les valeurs sont des tableaux de messages lisibles par l'humain.",
            "content": {
              "application/json": {
                "examples": {
                  "Advanced (AES) not available": {
                    "value": {
                      "features": {
                        "signature_level": [
                          "Node 'signature': Advanced (AES) is not available yet (aes_not_available)."
                        ]
                      }
                    }
                  },
                  "Signature step with no document": {
                    "value": {
                      "features": {
                        "non_field_errors": [
                          "Node 'signature': Add a document to sign, or let each session bring its own."
                        ]
                      }
                    }
                  },
                  "Missing feature": {
                    "value": {
                      "features": [
                        "At least one feature is required."
                      ]
                    }
                  },
                  "Unknown top-level field": {
                    "value": {
                      "workflow_type": [
                        "The v3 workflow API only accepts `workflow_label`, `is_default`, `status`, `features`, `is_white_label_enabled`, `is_desktop_allowed`, `max_retry_attempts`, `retry_window_days`, `session_expiration_time`, `face_liveness_max_attempts`, `face_match_max_attempts`."
                      ]
                    }
                  },
                  "Unknown feature": {
                    "value": {
                      "features": [
                        "Invalid feature 'FOO'. Allowed values: AGE_ESTIMATION, AML, DATABASE_VALIDATION, EMAIL_VERIFICATION, FACE_MATCH, IP_ANALYSIS, KYB_DOCUMENTS, KYB_KEY_PEOPLE, KYB_REGISTRY, LIVENESS, NFC, OCR, PHONE_VERIFICATION, PROOF_OF_ADDRESS, QUESTIONNAIRE."
                      ]
                    }
                  },
                  "Ordering": {
                    "value": {
                      "features": [
                        "Feature 'FACE_MATCH' must appear after one of: OCR."
                      ]
                    }
                  },
                  "Questionnaire not found": {
                    "value": {
                      "features": "Questionnaire '11111111-2222-3333-4444-555555555555' was not found for this application. Create the questionnaire first, then use its questionnaire_id."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé API est manquante, malformée, expirée ou restreinte à une autre application. Actualisez via l'[API Auth](/fr/auth-api/get-credentials) et réessayez.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Type de média non pris en charge. Définissez `Content-Type: application/json` et envoyez un corps JSON."
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue lors de la création du workflow. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/workflows/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"workflow_label\": \"Standard KYC\",\n    \"features\": [\n      {\"feature\": \"OCR\"},\n      {\"feature\": \"LIVENESS\", \"config\": {\"face_liveness_method\": \"passive\"}},\n      {\"feature\": \"FACE_MATCH\", \"config\": {\"face_match_score_decline_threshold\": 40, \"face_match_score_review_threshold\": 60}}\n    ]\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.workflows.create(\n    workflow_label=\"Standard KYC\",\n    features=[{\n        \"feature\": \"OCR\",\n        \"config\": {\"duplicated_user_action\": \"review\"},\n    }, {\n        \"feature\": \"LIVENESS\",\n        \"config\": {\"face_liveness_method\": \"passive\"},\n    }, {\n        \"feature\": \"FACE_MATCH\",\n        \"config\": {\"face_match_score_decline_threshold\": 40, \"face_match_score_review_threshold\": 60},\n    }],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.workflows.create({\n  workflow_label: \"Standard KYC\",\n  features: [{\n    feature: \"OCR\",\n    config: { duplicated_user_action: \"review\" },\n  }, {\n    feature: \"LIVENESS\",\n    config: { face_liveness_method: \"passive\" },\n  }, {\n    feature: \"FACE_MATCH\",\n    config: { face_match_score_decline_threshold: 40, face_match_score_review_threshold: 60 },\n  }],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Workflows.Create(ctx, didit.SimpleWorkflowRequest{\n\tWorkflowLabel: didit.String(\"Standard KYC\"),\n\tFeatures: []didit.SimpleWorkflowFeature{{\n\t\tFeature: \"OCR\",\n\t\tConfig:  didit.Some(map[string]any{\"duplicated_user_action\": \"review\"}),\n\t}, {\n\t\tFeature: \"LIVENESS\",\n\t\tConfig:  didit.Some(map[string]any{\"face_liveness_method\": \"passive\"}),\n\t}, {\n\t\tFeature: \"FACE_MATCH\",\n\t\tConfig:  didit.Some(map[string]any{\"face_match_score_decline_threshold\": 40, \"face_match_score_review_threshold\": 60}),\n\t}},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.SimpleWorkflowFeature;\nimport me.didit.types.SimpleWorkflowRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.workflows().create(SimpleWorkflowRequest.builder()\n        .workflowLabel(\"Standard KYC\")\n        .features(List.of(\n                SimpleWorkflowFeature.builder()\n                        .feature(SimpleWorkflowFeature.Feature.of(\"OCR\"))\n                        .config(Map.of(\"duplicated_user_action\", \"review\"))\n                        .build(),\n                SimpleWorkflowFeature.builder()\n                        .feature(SimpleWorkflowFeature.Feature.of(\"LIVENESS\"))\n                        .config(Map.of(\"face_liveness_method\", \"passive\"))\n                        .build(),\n                SimpleWorkflowFeature.builder()\n                        .feature(SimpleWorkflowFeature.Feature.of(\"FACE_MATCH\"))\n                        .config(Map.of(\"face_match_score_decline_threshold\", 40, \"face_match_score_review_threshold\", 60))\n                        .build()))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->workflows->create([\n    'workflow_label' => 'Standard KYC',\n    'features' => [[\n        'feature' => 'OCR',\n        'config' => ['duplicated_user_action' => 'review'],\n    ], [\n        'feature' => 'LIVENESS',\n        'config' => ['face_liveness_method' => 'passive'],\n    ], [\n        'feature' => 'FACE_MATCH',\n        'config' => ['face_match_score_decline_threshold' => 40, 'face_match_score_review_threshold' => 60],\n    ]],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.workflows.create(\n  workflow_label: \"Standard KYC\",\n  features: [{\n    feature: \"OCR\",\n    config: { duplicated_user_action: \"review\" },\n  }, {\n    feature: \"LIVENESS\",\n    config: { face_liveness_method: \"passive\" },\n  }, {\n    feature: \"FACE_MATCH\",\n    config: { face_match_score_decline_threshold: 40, face_match_score_review_threshold: 60 },\n  }]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Workflows.CreateAsync(new SimpleWorkflowRequest\n{\n    WorkflowLabel = \"Standard KYC\",\n    Features = new SimpleWorkflowFeature[]\n    {\n        new()\n        {\n            Feature = \"OCR\",\n            Config = new Dictionary<string, object> { [\"duplicated_user_action\"] = \"review\" },\n        },\n        new()\n        {\n            Feature = \"LIVENESS\",\n            Config = new Dictionary<string, object> { [\"face_liveness_method\"] = \"passive\" },\n        },\n        new()\n        {\n            Feature = \"FACE_MATCH\",\n            Config = new Dictionary<string, object> { [\"face_match_score_decline_threshold\"] = 40, [\"face_match_score_review_threshold\"] = 60 },\n        },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/workflows/{settings_uuid}/": {
      "get": {
        "summary": "Obtenir le workflow",
        "description": "Récupérer la configuration complète d'une version de workflow par `settings_uuid` : activations des fonctionnalités, seuils, documents autorisés, graphe, politique de réessai, rappels et tarifs.",
        "operationId": "get_workflow",
        "x-didit-sdk": {
          "resource": "workflows",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Workflows"
        ],
        "parameters": [
          {
            "name": "settings_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID par version du workflow (la valeur `uuid` renvoyée par l'endpoint de liste). Chaque version d'un workflow possède son propre `settings_uuid`."
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration complète du workflow. Le format correspond à la sérialisation brute de `VerificationSettings` (~190 champs : chaque activation de fonctionnalité, seuil, action sur avertissement, configuration des documents autorisés, le `workflow_graph`, la politique de nouvelle tentative, les callbacks et les tarifs). L'exemple ci-dessous est abrégé. Remarques : `features` est une chaîne reliée par `\" + \"` (par ex. `\"OCR + LIVENESS\"`), les prix sont des nombres JSON, et `is_editable` est à `true` uniquement pour les versions `draft`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowDetail"
                },
                "examples": {
                  "KYC workflow with face match (abbreviated)": {
                    "value": {
                      "uuid": "a1b2c3d4-5678-90ab-cdef-111111111111",
                      "workflow_id": "a1b2c3d4-5678-90ab-cdef-111111111111",
                      "workflow_label": "Standard KYC",
                      "workflow_type": "kyc",
                      "is_default": true,
                      "is_archived": false,
                      "is_liveness_enabled": true,
                      "face_liveness_method": "passive",
                      "face_liveness_score_decline_threshold": 50,
                      "face_liveness_score_review_threshold": 70,
                      "is_face_match_enabled": true,
                      "face_match_score_decline_threshold": 40,
                      "face_match_score_review_threshold": 60,
                      "is_aml_enabled": false,
                      "is_phone_verification_enabled": false,
                      "is_email_verification_enabled": false,
                      "is_database_validation_enabled": false,
                      "is_ip_analysis_enabled": false,
                      "is_nfc_enabled": false,
                      "duplicated_user_action": "no_action",
                      "documents_allowed": {
                        "ESP": {
                          "P": {
                            "sides": 1,
                            "enabled": 1,
                            "subtypes": [
                              "EPASSPORT",
                              "PASSPORT_GENERIC"
                            ],
                            "preferred_characters": "latin",
                            "expiration_check_mode": "strict"
                          }
                        }
                      },
                      "max_retry_attempts": 3,
                      "retry_window_days": 7,
                      "session_expiration_time": 604800,
                      "version": 2,
                      "status": "published",
                      "published_at": "2026-04-12T10:30:00Z",
                      "is_simple_workflow": false,
                      "is_editable": false,
                      "workflow_url": "https://verify.didit.me/u/_yljPOx8RWG3UAz5ZRQGVQ",
                      "total_price": 0.15,
                      "min_price": 0.15,
                      "max_price": 0.15,
                      "features": "OCR + LIVENESS + FACE_MATCH",
                      "created_at": "2025-01-15T10:30:00Z",
                      "updated_at": "2026-04-12T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun workflow avec ce `settings_uuid` n'existe pour l'application authentifiée. Soit l'UUID est incorrect, soit il appartient à une autre application — Didit ne fait délibérément pas la distinction entre les deux cas afin d'éviter de révéler l'existence d'enregistrements inter-applications.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X GET 'https://verification.didit.me/v3/workflows/a1b2c3d4-5678-90ab-cdef-111111111111/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.workflows.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.workflows.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Workflows.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.workflows().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->workflows->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.workflows.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Workflows.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour le workflow",
        "description": "Mettre à jour un workflow. La gestion des versions dépend du champ `status` envoyé et de l'état actuel de la version : (1) aucun `status` sur une version **publiée** → la version publiée est mise à jour sur place (mêmes `uuid` et `version`) ; (2) aucun `status` sur un **brouillon** → le brouillon est mis à jour et immédiatement publié ; (3) `status: \"published\"` sur une version **publiée** → une NOUVELLE version publiée est créée sous le même `workflow_id` (nouvel `uuid`, `version` + 1) et renvoyée, et tout brouillon existant dans le groupe est supprimé ; (4) `status: \"draft\"` conserve un brouillon comme brouillon (enregistrement automatique) mais est rejeté avec un code 400 sur une version publiée (`\"Cannot revert a published version to draft.\"`). Le corps accepte la même liste blanche stricte de champs qu'à la création — les clés inconnues sont rejetées avec un code 400.",
        "operationId": "update_workflow",
        "x-didit-sdk": {
          "resource": "workflows",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Workflows"
        ],
        "parameters": [
          {
            "name": "settings_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID par version du workflow à mettre à jour."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimpleWorkflowUpdateRequest"
              },
              "examples": {
                "Replace features": {
                  "summary": "Envoyez l'ordre complet souhaité pour les fonctionnalités",
                  "value": {
                    "features": [
                      {
                        "feature": "OCR"
                      },
                      {
                        "feature": "AML"
                      }
                    ]
                  }
                },
                "Rename": {
                  "summary": "Renommer un workflow",
                  "value": {
                    "workflow_label": "Premium KYC"
                  }
                },
                "Set as default": {
                  "summary": "Définir ce workflow comme workflow par défaut de l'application",
                  "value": {
                    "is_default": true
                  }
                },
                "Update config": {
                  "summary": "Modifier la configuration de la fonctionnalité",
                  "value": {
                    "features": [
                      {
                        "feature": "OCR"
                      },
                      {
                        "feature": "LIVENESS",
                        "config": {
                          "face_liveness_method": "passive"
                        }
                      }
                    ]
                  }
                },
                "Publish a draft": {
                  "summary": "Promouvoir un brouillon pour le publier",
                  "value": {
                    "status": "published"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Workflow mis à jour. Le corps contient la configuration COMPLÈTE de la version résultante (même structure brute `VerificationSettings` que `GET /v3/workflows/{settings_uuid}/`). Lorsque la mise à jour a créé une nouvelle version (`status: \"published\"` envoyé sur une ligne publiée), les valeurs `uuid` et `version` renvoyées diffèrent de celles que vous avez modifiées — utilisez l'`uuid` renvoyé pour les appels ultérieurs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowDetail"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — une clé de premier niveau en dehors de la liste autorisée, une fonctionnalité inconnue, un ordonnancement invalide, un seuil hors limites, la référence à un questionnaire inexistant, une fonctionnalité `SIGNATURE` qui passerait en production sans document à signer, une nouvelle fonctionnalité `SIGNATURE` avec `signature_level: \"aes\"` alors que la signature avancée (AES) n'est pas disponible (`aes_not_available`, voir `signature_availability` sur le workflow ; une étape qui stocke déjà `aes` la conserve), ou `status: \"draft\"` envoyé pour une version publiée (`\"Cannot revert a published version to draft.\"`). Le corps de la réponse est une erreur de validation DRF indexée par nom de champ."
          },
          "403": {
            "description": "Clé API manquante ou invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun workflow avec ce `settings_uuid` n'existe pour l'application authentifiée."
          },
          "415": {
            "description": "Type de média non pris en charge. Définissez `Content-Type: application/json`."
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/workflows/a1b2c3d4-5678-90ab-cdef-111111111111/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"workflow_label\": \"Premium KYC\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.workflows.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    features=[{\n        \"feature\": \"OCR\",\n    }, {\n        \"feature\": \"AML\",\n    }],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.workflows.update(\"11111111-2222-3333-4444-555555555555\", {\n  features: [{\n    feature: \"OCR\",\n  }, {\n    feature: \"AML\",\n  }],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Workflows.Update(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SimpleWorkflowUpdateRequest{\n\tFeatures: didit.Some([]didit.SimpleWorkflowFeature{{\n\t\tFeature: \"OCR\",\n\t}, {\n\t\tFeature: \"AML\",\n\t}}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.SimpleWorkflowFeature;\nimport me.didit.types.SimpleWorkflowUpdateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.workflows().update(\"11111111-2222-3333-4444-555555555555\", SimpleWorkflowUpdateRequest.builder()\n        .features(List.of(\n                SimpleWorkflowFeature.builder()\n                        .feature(SimpleWorkflowFeature.Feature.of(\"OCR\"))\n                        .build(),\n                SimpleWorkflowFeature.builder()\n                        .feature(SimpleWorkflowFeature.Feature.of(\"AML\"))\n                        .build()))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->workflows->update('11111111-2222-3333-4444-555555555555', [\n    'features' => [[\n        'feature' => 'OCR',\n    ], [\n        'feature' => 'AML',\n    ]],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.workflows.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  features: [{\n    feature: \"OCR\",\n  }, {\n    feature: \"AML\",\n  }]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Workflows.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", new SimpleWorkflowUpdateRequest\n{\n    Features = new SimpleWorkflowFeature[]\n    {\n        new()\n        {\n            Feature = \"OCR\",\n        },\n        new()\n        {\n            Feature = \"AML\",\n        },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer le workflow",
        "description": "Supprime définitivement une version de workflow (aucun retour en arrière possible). Les sessions existantes conservent leurs résultats de vérification mais leur référence de workflow est effacée ; les autres versions du même groupe `workflow_id` ne sont pas supprimées.",
        "operationId": "delete_workflow",
        "x-didit-sdk": {
          "resource": "workflows",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Workflows"
        ],
        "parameters": [
          {
            "name": "settings_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID par version du workflow à supprimer."
          }
        ],
        "responses": {
          "204": {
            "description": "Workflow supprimé. Le corps de la réponse est vide."
          },
          "403": {
            "description": "Clé API manquante ou invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun workflow avec ce `settings_uuid` n'existe pour l'application authentifiée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/workflows/a1b2c3d4-5678-90ab-cdef-111111111111/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.workflows.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.workflows.delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.Workflows.Delete(ctx, \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.workflows().delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->workflows->delete('11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.workflows.delete(\"11111111-2222-3333-4444-555555555555\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.Workflows.DeleteAsync(\"11111111-2222-3333-4444-555555555555\");"
          }
        ]
      }
    },
    "/v3/questionnaires/": {
      "get": {
        "summary": "Lister les questionnaires",
        "description": "Lister vos questionnaires, les plus récents en premier, dans une enveloppe de pagination limit/offset (`{count, next, previous, results}`, taille de page par défaut 50). Chaque ligne correspond à une version ; `questionnaire_group_id` est l'identifiant de groupe stable correspondant à la dernière version `published`.",
        "operationId": "list_questionnaires",
        "x-didit-sdk": {
          "resource": "questionnaires",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Questionnaires"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            },
            "description": "Taille de page (nombre de questionnaires par page)."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Nombre de lignes à ignorer avant le premier questionnaire retourné."
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de questionnaires triés par `created_at` décroissant, encapsulée dans l'enveloppe de pagination. Chaque élément de `results` est un `QuestionnaireListItem`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre total de versions de questionnaire pour l'application."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/QuestionnaireListItem"
                      }
                    }
                  }
                },
                "examples": {
                  "One questionnaire": {
                    "summary": "Un simple questionnaire bilingue",
                    "value": {
                      "count": 1,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "11111111-2222-3333-4444-555555555555",
                          "title": "KYC Questionnaire",
                          "description": "Additional verification questions",
                          "languages": [
                            "en",
                            "es"
                          ],
                          "default_language": "en",
                          "is_active": true,
                          "is_simple_questionnaire": true,
                          "created_at": "2026-04-23T09:55:00Z",
                          "updated_at": "2026-04-23T10:00:00Z",
                          "question_types": [
                            "SHORT_TEXT",
                            "MULTIPLE_CHOICE",
                            "FILE_UPLOAD"
                          ],
                          "workflow_names": [],
                          "questionnaire_group_id": "11111111-2222-3333-4444-555555555555",
                          "version": 1,
                          "status": "published",
                          "published_at": "2026-04-23T10:00:00Z",
                          "is_editable": false
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue lors de la construction de la liste. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X GET 'https://verification.didit.me/v3/questionnaires/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.questionnaires.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.questionnaires.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Questionnaires.ListAutoPaging(ctx, didit.QuestionnairesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.questionnaires().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->questionnaires->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.questionnaires.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Questionnaires.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "summary": "Créer un questionnaire",
        "description": "Créez un questionnaire linéaire simple. Envoyez `form_elements` dans l'ordre d'affichage ; les branchements et les groupes répétables nécessitent la Console. Défini par défaut sur `published` v1.",
        "operationId": "create_questionnaire",
        "x-didit-sdk": {
          "resource": "questionnaires",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Questionnaires"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimpleQuestionnaireRequest"
              },
              "examples": {
                "Simple": {
                  "summary": "Questionnaire de base",
                  "value": {
                    "title": "Customer Onboarding",
                    "description": "Additional information needed for verification",
                    "default_language": "en",
                    "languages": [
                      "en"
                    ],
                    "is_active": true,
                    "form_elements": [
                      {
                        "id": "occupation",
                        "element_type": "short_text",
                        "label": {
                          "en": "What is your occupation?"
                        },
                        "is_required": true,
                        "placeholder": {
                          "en": "Software engineer"
                        }
                      },
                      {
                        "id": "source_of_funds",
                        "element_type": "multiple_choice",
                        "label": {
                          "en": "Source of funds"
                        },
                        "is_required": true,
                        "options": [
                          {
                            "value": "employment",
                            "label": {
                              "en": "Employment"
                            }
                          },
                          {
                            "value": "business",
                            "label": {
                              "en": "Business"
                            }
                          },
                          {
                            "value": "investments",
                            "label": {
                              "en": "Investments"
                            }
                          },
                          {
                            "value": "other",
                            "label": {
                              "en": "Other"
                            }
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Questionnaire créé. La réponse inclut le `questionnaire_id` — conservez-le pour référencer ce questionnaire dans les workflows ou lors de futurs appels de mise à jour/suppression.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionnaireDetail"
                },
                "examples": {
                  "Created": {
                    "value": {
                      "questionnaire_id": "11111111-2222-3333-4444-555555555555",
                      "title": "Customer Onboarding",
                      "description": "Additional information needed for verification",
                      "languages": [
                        "en"
                      ],
                      "default_language": "en",
                      "is_active": true,
                      "is_simple_questionnaire": true,
                      "graph": {
                        "start_node": "occupation",
                        "nodes": {
                          "occupation": {
                            "element_type": "SHORT_TEXT",
                            "is_required": true,
                            "title": {
                              "en": "What is your occupation?"
                            },
                            "next": "source_of_funds"
                          },
                          "source_of_funds": {
                            "element_type": "MULTIPLE_CHOICE",
                            "is_required": true,
                            "title": {
                              "en": "Source of funds"
                            },
                            "choices": [
                              {
                                "value": "employment",
                                "label": {
                                  "en": "Employment"
                                }
                              },
                              {
                                "value": "business",
                                "label": {
                                  "en": "Business"
                                }
                              }
                            ],
                            "next": null
                          }
                        }
                      },
                      "sections": [],
                      "questionnaire_group_id": "11111111-2222-3333-4444-555555555555",
                      "version": 1,
                      "status": "published",
                      "published_at": "2026-04-23T10:00:00Z",
                      "is_editable": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Causes courantes : un `element_type` inconnu, un champ traduisible sans traduction pour l'une des `languages`, `languages` ne contenant pas `en`, `default_language` absent de `languages`, une option sans `label`, une question comportant `branches`/`required_if`/`repeatable_config` (non pris en charge par cet endpoint), ou l'envoi d'un `graph` brut au lieu de `form_elements`. Le corps est une erreur de validation DRF indexée par nom de champ.",
            "content": {
              "application/json": {
                "examples": {
                  "Graph not accepted": {
                    "value": {
                      "graph": "The v3 questionnaire API only accepts simple `form_elements`, not `graph`."
                    }
                  },
                  "Missing label": {
                    "value": {
                      "form_elements": [
                        {
                          "label": [
                            "This field is required."
                          ]
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Type de média non pris en charge. Définissez `Content-Type: application/json` et envoyez un corps JSON."
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue lors de la création du questionnaire. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST 'https://verification.didit.me/v3/questionnaires/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"title\": \"Customer Onboarding\",\n    \"default_language\": \"en\",\n    \"languages\": [\"en\"],\n    \"form_elements\": [\n      {\n        \"id\": \"occupation\",\n        \"element_type\": \"short_text\",\n        \"label\": {\"en\": \"What is your occupation?\"},\n        \"is_required\": true\n      }\n    ]\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.questionnaires.create(\n    title=\"Customer Onboarding\",\n    description=\"Additional information needed for verification\",\n    languages=[\"en\"],\n    default_language=\"en\",\n    is_active=True,\n    form_elements=[{\n        \"id\": \"occupation\",\n        \"element_type\": \"short_text\",\n        \"label\": {\"en\": \"What is your occupation?\"},\n        \"placeholder\": {\"en\": \"Software engineer\"},\n        \"is_required\": True,\n    }, {\n        \"id\": \"source_of_funds\",\n        \"element_type\": \"multiple_choice\",\n        \"label\": {\"en\": \"Source of funds\"},\n        \"is_required\": True,\n        \"options\": [{\n            \"value\": \"employment\",\n            \"label\": {\"en\": \"Employment\"},\n        }, {\n            \"value\": \"business\",\n            \"label\": {\"en\": \"Business\"},\n        }, {\n            \"value\": \"investments\",\n            \"label\": {\"en\": \"Investments\"},\n        }, {\n            \"value\": \"other\",\n            \"label\": {\"en\": \"Other\"},\n        }],\n    }],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.questionnaires.create({\n  title: \"Customer Onboarding\",\n  description: \"Additional information needed for verification\",\n  languages: [\"en\"],\n  default_language: \"en\",\n  is_active: true,\n  form_elements: [{\n    id: \"occupation\",\n    element_type: \"short_text\",\n    label: { en: \"What is your occupation?\" },\n    placeholder: { en: \"Software engineer\" },\n    is_required: true,\n  }, {\n    id: \"source_of_funds\",\n    element_type: \"multiple_choice\",\n    label: { en: \"Source of funds\" },\n    is_required: true,\n    options: [{\n      value: \"employment\",\n      label: { en: \"Employment\" },\n    }, {\n      value: \"business\",\n      label: { en: \"Business\" },\n    }, {\n      value: \"investments\",\n      label: { en: \"Investments\" },\n    }, {\n      value: \"other\",\n      label: { en: \"Other\" },\n    }],\n  }],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Questionnaires.Create(ctx, didit.SimpleQuestionnaireRequest{\n\tTitle:           \"Customer Onboarding\",\n\tDescription:     didit.String(\"Additional information needed for verification\"),\n\tLanguages:       []string{\"en\"},\n\tDefaultLanguage: didit.String(\"en\"),\n\tIsActive:        didit.Bool(true),\n\tFormElements: []didit.SimpleQuestionnaireElement{{\n\t\tID:          didit.String(\"occupation\"),\n\t\tElementType: \"short_text\",\n\t\tLabel:       map[string]string{\"en\": \"What is your occupation?\"},\n\t\tPlaceholder: didit.Some(map[string]string{\"en\": \"Software engineer\"}),\n\t\tIsRequired:  didit.Bool(true),\n\t}, {\n\t\tID:          didit.String(\"source_of_funds\"),\n\t\tElementType: \"multiple_choice\",\n\t\tLabel:       map[string]string{\"en\": \"Source of funds\"},\n\t\tIsRequired:  didit.Bool(true),\n\t\tOptions: didit.Some([]didit.SimpleQuestionnaireElementOptions{{\n\t\t\tValue: didit.String(\"employment\"),\n\t\t\tLabel: map[string]string{\"en\": \"Employment\"},\n\t\t}, {\n\t\t\tValue: didit.String(\"business\"),\n\t\t\tLabel: map[string]string{\"en\": \"Business\"},\n\t\t}, {\n\t\t\tValue: didit.String(\"investments\"),\n\t\t\tLabel: map[string]string{\"en\": \"Investments\"},\n\t\t}, {\n\t\t\tValue: didit.String(\"other\"),\n\t\t\tLabel: map[string]string{\"en\": \"Other\"},\n\t\t}}),\n\t}},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.SimpleQuestionnaireElement;\nimport me.didit.types.SimpleQuestionnaireRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.questionnaires().create(SimpleQuestionnaireRequest.builder()\n        .title(\"Customer Onboarding\")\n        .description(\"Additional information needed for verification\")\n        .languages(List.of(\"en\"))\n        .defaultLanguage(\"en\")\n        .isActive(true)\n        .formElements(List.of(\n                SimpleQuestionnaireElement.builder()\n                        .id(\"occupation\")\n                        .elementType(SimpleQuestionnaireElement.ElementType.of(\"short_text\"))\n                        .label(Map.of(\"en\", \"What is your occupation?\"))\n                        .placeholder(Map.of(\"en\", \"Software engineer\"))\n                        .isRequired(true)\n                        .build(),\n                SimpleQuestionnaireElement.builder()\n                        .id(\"source_of_funds\")\n                        .elementType(SimpleQuestionnaireElement.ElementType.of(\"multiple_choice\"))\n                        .label(Map.of(\"en\", \"Source of funds\"))\n                        .isRequired(true)\n                        .options(List.of(\n                                SimpleQuestionnaireElement.Options.builder()\n                                        .value(\"employment\")\n                                        .label(Map.of(\"en\", \"Employment\"))\n                                        .build(),\n                                SimpleQuestionnaireElement.Options.builder()\n                                        .value(\"business\")\n                                        .label(Map.of(\"en\", \"Business\"))\n                                        .build(),\n                                SimpleQuestionnaireElement.Options.builder()\n                                        .value(\"investments\")\n                                        .label(Map.of(\"en\", \"Investments\"))\n                                        .build(),\n                                SimpleQuestionnaireElement.Options.builder()\n                                        .value(\"other\")\n                                        .label(Map.of(\"en\", \"Other\"))\n                                        .build()))\n                        .build()))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->questionnaires->create([\n    'title' => 'Customer Onboarding',\n    'description' => 'Additional information needed for verification',\n    'languages' => ['en'],\n    'default_language' => 'en',\n    'is_active' => true,\n    'form_elements' => [[\n        'id' => 'occupation',\n        'element_type' => 'short_text',\n        'label' => ['en' => 'What is your occupation?'],\n        'placeholder' => ['en' => 'Software engineer'],\n        'is_required' => true,\n    ], [\n        'id' => 'source_of_funds',\n        'element_type' => 'multiple_choice',\n        'label' => ['en' => 'Source of funds'],\n        'is_required' => true,\n        'options' => [[\n            'value' => 'employment',\n            'label' => ['en' => 'Employment'],\n        ], [\n            'value' => 'business',\n            'label' => ['en' => 'Business'],\n        ], [\n            'value' => 'investments',\n            'label' => ['en' => 'Investments'],\n        ], [\n            'value' => 'other',\n            'label' => ['en' => 'Other'],\n        ]],\n    ]],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.questionnaires.create(\n  title: \"Customer Onboarding\",\n  description: \"Additional information needed for verification\",\n  languages: [\"en\"],\n  default_language: \"en\",\n  is_active: true,\n  form_elements: [{\n    id: \"occupation\",\n    element_type: \"short_text\",\n    label: { en: \"What is your occupation?\" },\n    placeholder: { en: \"Software engineer\" },\n    is_required: true,\n  }, {\n    id: \"source_of_funds\",\n    element_type: \"multiple_choice\",\n    label: { en: \"Source of funds\" },\n    is_required: true,\n    options: [{\n      value: \"employment\",\n      label: { en: \"Employment\" },\n    }, {\n      value: \"business\",\n      label: { en: \"Business\" },\n    }, {\n      value: \"investments\",\n      label: { en: \"Investments\" },\n    }, {\n      value: \"other\",\n      label: { en: \"Other\" },\n    }],\n  }]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Questionnaires.CreateAsync(new SimpleQuestionnaireRequest\n{\n    Title = \"Customer Onboarding\",\n    Description = \"Additional information needed for verification\",\n    Languages = new string[] { \"en\" },\n    DefaultLanguage = \"en\",\n    IsActive = true,\n    FormElements = new SimpleQuestionnaireElement[]\n    {\n        new()\n        {\n            Id = \"occupation\",\n            ElementType = \"short_text\",\n            Label = new Dictionary<string, string> { [\"en\"] = \"What is your occupation?\" },\n            Placeholder = new Dictionary<string, string> { [\"en\"] = \"Software engineer\" },\n            IsRequired = true,\n        },\n        new()\n        {\n            Id = \"source_of_funds\",\n            ElementType = \"multiple_choice\",\n            Label = new Dictionary<string, string> { [\"en\"] = \"Source of funds\" },\n            IsRequired = true,\n            Options = new SimpleQuestionnaireElementOptions[]\n            {\n                new()\n                {\n                    Value = \"employment\",\n                    Label = new Dictionary<string, string> { [\"en\"] = \"Employment\" },\n                },\n                new()\n                {\n                    Value = \"business\",\n                    Label = new Dictionary<string, string> { [\"en\"] = \"Business\" },\n                },\n                new()\n                {\n                    Value = \"investments\",\n                    Label = new Dictionary<string, string> { [\"en\"] = \"Investments\" },\n                },\n                new()\n                {\n                    Value = \"other\",\n                    Label = new Dictionary<string, string> { [\"en\"] = \"Other\" },\n                },\n            },\n        },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/questionnaires/{questionnaire_uuid}/": {
      "get": {
        "summary": "Obtenir le questionnaire",
        "description": "Récupérer le détail complet du questionnaire pour une version par `questionnaire_uuid` : titre, `languages`, `graph` canonique, `sections` dérivées et métadonnées de version.",
        "operationId": "get_questionnaire",
        "x-didit-sdk": {
          "resource": "questionnaires",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Questionnaires"
        ],
        "parameters": [
          {
            "name": "questionnaire_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID par version du questionnaire (la valeur `uuid` renvoyée par l'endpoint de liste, également renvoyée sous `questionnaire_id` sur les endpoints de détail)."
          }
        ],
        "responses": {
          "200": {
            "description": "Détails complets du questionnaire incluant le `graph` canonique, la vue dérivée `sections`, les métadonnées de version et `is_editable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionnaireDetail"
                },
                "examples": {
                  "Published questionnaire": {
                    "value": {
                      "questionnaire_id": "11111111-2222-3333-4444-555555555555",
                      "title": "Customer Onboarding",
                      "description": "Additional information needed for verification",
                      "languages": [
                        "en"
                      ],
                      "default_language": "en",
                      "is_active": true,
                      "is_simple_questionnaire": true,
                      "graph": {
                        "start_node": "occupation",
                        "nodes": {
                          "occupation": {
                            "element_type": "SHORT_TEXT",
                            "is_required": true,
                            "title": {
                              "en": "What is your occupation?"
                            },
                            "next": "source_of_funds"
                          },
                          "source_of_funds": {
                            "element_type": "MULTIPLE_CHOICE",
                            "is_required": true,
                            "title": {
                              "en": "Source of funds"
                            },
                            "choices": [
                              {
                                "value": "employment",
                                "label": {
                                  "en": "Employment"
                                }
                              },
                              {
                                "value": "business",
                                "label": {
                                  "en": "Business"
                                }
                              }
                            ],
                            "next": null
                          }
                        }
                      },
                      "sections": [
                        {
                          "title": {},
                          "description": {},
                          "items": [
                            {
                              "uuid": "11111111-2222-3333-4444-666666666666",
                              "value": "occupation",
                              "element_type": "SHORT_TEXT",
                              "is_required": true,
                              "title": {
                                "en": "What is your occupation?"
                              }
                            }
                          ]
                        }
                      ],
                      "questionnaire_group_id": "11111111-2222-3333-4444-555555555555",
                      "version": 1,
                      "status": "published",
                      "published_at": "2026-04-23T10:00:00Z",
                      "is_editable": false
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun questionnaire avec ce `questionnaire_uuid` n'existe pour l'application authentifiée. Soit l'UUID est incorrect, soit il appartient à une autre application — l'API ne fait délibérément pas la distinction entre les deux cas.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X GET 'https://verification.didit.me/v3/questionnaires/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.questionnaires.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.questionnaires.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Questionnaires.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.questionnaires().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->questionnaires->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.questionnaires.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Questionnaires.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour le questionnaire",
        "description": "Mettre à jour un questionnaire. La gestion des versions dépend du champ `status` envoyé et de l'état actuel de la version : (1) aucun `status` sur une version **publiée** → la version publiée est mise à jour sur place (mêmes `questionnaire_id` et `version`) ; (2) aucun `status` sur un **brouillon** → le brouillon est mis à jour et immédiatement publié ; (3) `status: \"published\"` sur une version **publiée** → une NOUVELLE version publiée est créée sous le même `questionnaire_group_id` (nouveau `questionnaire_id`, `version` + 1) et renvoyée, et tout brouillon existant dans le groupe est supprimé ; (4) `status: \"draft\"` conserve un brouillon comme brouillon (enregistrement automatique) mais est rejeté avec un code 400 sur une version publiée (`\"Cannot revert a published version to draft.\"`).",
        "operationId": "update_questionnaire",
        "x-didit-sdk": {
          "resource": "questionnaires",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Questionnaires"
        ],
        "parameters": [
          {
            "name": "questionnaire_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID par version du questionnaire à mettre à jour."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimpleQuestionnaireUpdateRequest"
              },
              "examples": {
                "Rename": {
                  "summary": "Renommer un questionnaire",
                  "value": {
                    "title": "Updated Customer Onboarding"
                  }
                },
                "Replace questions": {
                  "summary": "Remplacer la liste complète et linéaire des questions",
                  "value": {
                    "form_elements": [
                      {
                        "id": "occupation",
                        "element_type": "short_text",
                        "label": {
                          "en": "What is your occupation?"
                        },
                        "is_required": true
                      },
                      {
                        "id": "source_of_funds",
                        "element_type": "multiple_choice",
                        "label": {
                          "en": "Source of funds"
                        },
                        "options": [
                          {
                            "value": "employment",
                            "label": {
                              "en": "Employment"
                            }
                          },
                          {
                            "value": "business",
                            "label": {
                              "en": "Business"
                            }
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Questionnaire mis à jour. Le corps correspond au dernier état de la version résultante — la version mise à jour sur place, ou la version publiée nouvellement créée lorsque vous avez envoyé `status: \"published\"` sur une ligne publiée (dans ce cas, `questionnaire_id` et `version` diffèrent de ceux que vous avez modifiés). `questionnaire_id` dans la réponse est l'UUID par version ; utilisez `questionnaire_group_id` si vous avez besoin de l'identifiant de groupe stable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionnaireDetail"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — `element_type` inconnu, traduction manquante, champs conditionnels/d'embranchement non pris en charge, `languages` ne contenant pas `en`, `default_language` absent de `languages`, option sans libellé, envoi d'un `graph` brut, ou `status: \"draft\"` sur une version publiée (`\"Cannot revert a published version to draft.\"`). Le corps de la réponse est une erreur de validation DRF indexée par nom de champ."
          },
          "403": {
            "description": "Clé API manquante ou invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun questionnaire avec ce `questionnaire_uuid` n'existe pour l'application authentifiée."
          },
          "415": {
            "description": "Type de média non pris en charge. Définissez `Content-Type: application/json`."
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/questionnaires/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"title\": \"Updated Customer Onboarding\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.questionnaires.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    title=\"Updated Customer Onboarding\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.questionnaires.update(\"11111111-2222-3333-4444-555555555555\", {\n  title: \"Updated Customer Onboarding\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Questionnaires.Update(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SimpleQuestionnaireUpdateRequest{\n\tTitle: didit.String(\"Updated Customer Onboarding\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SimpleQuestionnaireUpdateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.questionnaires().update(\"11111111-2222-3333-4444-555555555555\", SimpleQuestionnaireUpdateRequest.builder()\n        .title(\"Updated Customer Onboarding\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->questionnaires->update('11111111-2222-3333-4444-555555555555', [\n    'title' => 'Updated Customer Onboarding',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.questionnaires.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  title: \"Updated Customer Onboarding\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Questionnaires.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", new SimpleQuestionnaireUpdateRequest\n{\n    Title = \"Updated Customer Onboarding\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer le questionnaire",
        "description": "Supprime définitivement une version de questionnaire (aucun retour en arrière possible). Les réponses au questionnaire enregistrées et liées à cette version sont supprimées avec elle, et les sessions qui la référencent perdent ce lien ; les autres versions du même groupe ne sont pas supprimées. Les workflows qui la référençaient continuent de s'exécuter, mais l'étape de questionnaire ne peut plus la charger.",
        "operationId": "delete_questionnaire",
        "x-didit-sdk": {
          "resource": "questionnaires",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Questionnaires"
        ],
        "parameters": [
          {
            "name": "questionnaire_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID par version du questionnaire à supprimer."
          }
        ],
        "responses": {
          "204": {
            "description": "Questionnaire supprimé. Le corps de la réponse est vide."
          },
          "403": {
            "description": "Clé API manquante ou invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun questionnaire avec ce `questionnaire_uuid` n'existe pour l'application authentifiée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          },
          "500": {
            "description": "Erreur serveur inattendue. Peut être réessayé en toute sécurité."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/questionnaires/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.questionnaires.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.questionnaires.delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.Questionnaires.Delete(ctx, \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.questionnaires().delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->questionnaires->delete('11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.questionnaires.delete(\"11111111-2222-3333-4444-555555555555\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.Questionnaires.DeleteAsync(\"11111111-2222-3333-4444-555555555555\");"
          }
        ]
      }
    },
    "/v3/users/": {
      "get": {
        "summary": "Lister les utilisateurs",
        "description": "Lister les [utilisateurs](/entities/users) que Didit regroupe à partir des sessions KYC partageant le même `vendor_data` (chaîne libre, et NON un UUID), ainsi que les utilisateurs créés via l'API. Paginé, ordonné par `last_session_at` décroissant. Cet endpoint ne prend pas en charge les paramètres de filtrage ou de recherche — récupérez les pages et filtrez côté client.",
        "operationId": "list_users",
        "x-didit-sdk": {
          "resource": "users",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "description": "Taille de page. Vaut 50 par défaut si omis. Aucun maximum n'est imposé, mais conservez des pages de petite taille pour limiter la latence."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "description": "Décalage de départ (base zéro) du premier enregistrement à retourner. Privilégiez l'utilisation de l'URL `next` de la page précédente plutôt que de le calculer manuellement."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/users/?limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.users.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.users.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Users.ListAutoPaging(ctx, didit.UsersListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.users().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->users->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.users.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Users.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginée des utilisateurs avec statut de vérification, décompte des sessions et détail des fonctionnalités.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de lignes correspondantes — exact jusqu'à 100, plafonné à 100 au-delà pour des raisons de performance. Ne l'utilisez pas pour détecter la dernière page ; fiez-vous plutôt au fait que `next` soit `null`."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UserListItem"
                      }
                    }
                  }
                },
                "examples": {
                  "Example": {
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "didit_internal_id": "f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418",
                          "vendor_data": "user-abc-123",
                          "display_name": null,
                          "full_name": "John Michael Doe",
                          "date_of_birth": "1990-05-15",
                          "effective_name": "John Michael Doe",
                          "status": "ACTIVE",
                          "portrait_image_url": "https://<media-host>/...",
                          "session_count": 3,
                          "approved_count": 2,
                          "declined_count": 0,
                          "in_review_count": 1,
                          "issuing_states": [
                            "USA"
                          ],
                          "approved_emails": [
                            "john@example.com"
                          ],
                          "approved_phones": [
                            "+14155551234"
                          ],
                          "features": {
                            "ID_VERIFICATION": "Approved",
                            "LIVENESS": "Approved",
                            "FACE_MATCH": "Approved",
                            "AML": "Approved"
                          },
                          "features_list": [
                            {
                              "feature": "ID_VERIFICATION",
                              "status": "Approved"
                            },
                            {
                              "feature": "LIVENESS",
                              "status": "Approved"
                            },
                            {
                              "feature": "FACE_MATCH",
                              "status": "Approved"
                            },
                            {
                              "feature": "AML",
                              "status": "Approved"
                            }
                          ],
                          "last_session_at": "2025-06-15T10:30:00Z",
                          "last_activity_at": "2025-06-15T10:30:00Z",
                          "first_session_at": "2025-06-01T08:00:00Z",
                          "tags": [
                            {
                              "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                              "name": "VIP",
                              "color": "#2567FF"
                            }
                          ],
                          "created_at": "2025-06-01T08:00:00Z"
                        },
                        {
                          "didit_internal_id": "6ed99d53-e8f5-4cf8-9ac1-4a506cb40f6b",
                          "vendor_data": null,
                          "display_name": "Jane S.",
                          "full_name": "Jane Elizabeth Smith",
                          "date_of_birth": "1985-11-22",
                          "effective_name": "Jane S.",
                          "status": "FLAGGED",
                          "portrait_image_url": null,
                          "session_count": 1,
                          "approved_count": 0,
                          "declined_count": 0,
                          "in_review_count": 1,
                          "issuing_states": [],
                          "approved_emails": [],
                          "approved_phones": [],
                          "features": {
                            "ID_VERIFICATION": "In Review"
                          },
                          "features_list": [
                            {
                              "feature": "ID_VERIFICATION",
                              "status": "In Review"
                            }
                          ],
                          "last_session_at": "2025-06-20T14:00:00Z",
                          "last_activity_at": "2025-06-20T14:05:00Z",
                          "first_session_at": "2025-06-20T14:00:00Z",
                          "tags": [],
                          "created_at": "2025-06-20T14:00:00Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Aucun identifiant fourni. Les requêtes vers les chemins `/v3/users/*` sans en-tête `x-api-key` (ou token `Authorization: Bearer`) sont rejetées par le middleware d'authentification avant d'atteindre l'API.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing credentials": {
                    "value": {
                      "detail": "You must be authenticated with a valid access token to access this endpoint."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé ne peut pas lister les utilisateurs pour cette application. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/users/{vendor_data}/": {
      "get": {
        "summary": "Obtenir l'utilisateur",
        "description": "Récupère un [utilisateur](/entities/users) par `vendor_data` (correspondance exacte). Ajoute `metadata`, `comments` et `updated_at` à la vue sous forme de liste, et bascule `tags` vers la structure détaillée des liens de tags.",
        "operationId": "get_user",
        "x-didit-sdk": {
          "resource": "users",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "vendor_data",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Votre identifiant unique pour l'utilisateur — chaîne libre (PAS un UUID). Il s'agit de la même valeur que vous avez transmise en tant que `vendor_data` lors de la création de la session ayant introduit cet utilisateur pour la première fois, mise en correspondance exactement telle qu'envoyée.",
            "example": "user-abc-123"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/users/user-abc-123/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.users.retrieve(\n    \"user-abc-123\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.users.retrieve(\"user-abc-123\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Users.Retrieve(ctx, \"user-abc-123\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.users().retrieve(\"user-abc-123\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->users->retrieve('user-abc-123');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.users.retrieve(\"user-abc-123\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Users.RetrieveAsync(\"user-abc-123\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détails complets de l'utilisateur incluant les métadonnées, le journal des commentaires/d'activité et les données agrégées de session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDetailItem"
                },
                "examples": {
                  "Active user": {
                    "value": {
                      "didit_internal_id": "f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418",
                      "vendor_data": "user-abc-123",
                      "display_name": null,
                      "full_name": "John Michael Doe",
                      "date_of_birth": "1990-05-15",
                      "effective_name": "John Michael Doe",
                      "status": "ACTIVE",
                      "metadata": {
                        "tier": "premium",
                        "source": "website"
                      },
                      "portrait_image_url": "https://<media-host>/...",
                      "session_count": 3,
                      "approved_count": 2,
                      "declined_count": 0,
                      "in_review_count": 1,
                      "issuing_states": [
                        "USA"
                      ],
                      "approved_emails": [
                        "john@example.com"
                      ],
                      "approved_phones": [
                        "+14155551234"
                      ],
                      "features": {
                        "ID_VERIFICATION": "Approved",
                        "LIVENESS": "Approved",
                        "FACE_MATCH": "Approved",
                        "AML": "Approved"
                      },
                      "features_list": [
                        {
                          "feature": "ID_VERIFICATION",
                          "status": "Approved"
                        },
                        {
                          "feature": "LIVENESS",
                          "status": "Approved"
                        },
                        {
                          "feature": "FACE_MATCH",
                          "status": "Approved"
                        },
                        {
                          "feature": "AML",
                          "status": "Approved"
                        }
                      ],
                      "last_session_at": "2025-06-15T10:30:00Z",
                      "last_activity_at": "2025-06-15T10:30:00Z",
                      "first_session_at": "2025-06-01T08:00:00Z",
                      "tags": [
                        {
                          "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                          "tag": {
                            "uuid": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
                            "name": "VIP",
                            "color": "#2567FF",
                            "description": null,
                            "source": "custom",
                            "created_at": "2025-05-01T09:00:00Z",
                            "updated_at": "2025-05-01T09:00:00Z"
                          },
                          "added_by_email": "analyst@acme.com",
                          "added_by_name": "Jane Analyst",
                          "created_at": "2025-06-02T11:00:00Z"
                        }
                      ],
                      "comments": [
                        {
                          "uuid": "c1111111-2222-4333-8444-555555555555",
                          "comment_type": "STATUS_CHANGED",
                          "comment": null,
                          "actor_email": "analyst@acme.com",
                          "actor_name": "Jane Analyst",
                          "previous_status": "FLAGGED",
                          "new_status": "ACTIVE",
                          "previous_value": null,
                          "new_value": null,
                          "changed_fields": [],
                          "metadata": null,
                          "mentioned_emails": [],
                          "created_at": "2025-06-01T10:30:00Z"
                        }
                      ],
                      "created_at": "2025-06-01T08:00:00Z",
                      "updated_at": "2025-06-15T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Aucun identifiant fourni. Les requêtes vers les chemins `/v3/users/*` sans en-tête `x-api-key` (ou token `Authorization: Bearer`) sont rejetées par le middleware d'authentification avant d'atteindre l'API.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing credentials": {
                    "value": {
                      "detail": "You must be authenticated with a valid access token to access this endpoint."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API non valide ou révoquée, ou la clé ne peut pas lire les utilisateurs de cette application. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun utilisateur avec le `vendor_data` fourni n'existe pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour l'utilisateur",
        "description": "Mise à jour partielle d'un utilisateur : `display_name`, `full_name`, `date_of_birth`, `status`, `metadata`, `approved_emails`/`approved_phones`/`issuing_states`. `metadata` est entièrement remplacé. Modifier `status` ici fonctionne comme [Update User Status](#patch-/v3/users/-vendor_data-/update-status/) : cela enregistre une activité `STATUS_CHANGED` avec le `reason` facultatif, et `BLOCKED` ajoute le `vendor_data` à la liste de blocage du système (quitter l'état `BLOCKED` retire cette entrée). Les modifications apportées à `display_name`, `full_name`, `date_of_birth` ou `metadata` sont enregistrées en tant qu'activité `PROFILE_UPDATED`.",
        "operationId": "update_user",
        "x-didit-sdk": {
          "resource": "users",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "vendor_data",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Votre identifiant unique pour l'utilisateur (chaîne libre, PAS un UUID).",
            "example": "user-abc-123"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/users/user-abc-123/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"display_name\": \"Jane S.\", \"status\": \"FLAGGED\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.users.update(\n    \"user-abc-123\",\n    display_name=\"Jane S.\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.users.update(\"user-abc-123\", {\n  display_name: \"Jane S.\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Users.Update(ctx, \"user-abc-123\", didit.UsersUpdateParams{\n\tDisplayName: didit.String(\"Jane S.\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.UsersUpdateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.users().update(\"user-abc-123\", UsersUpdateParams.builder()\n        .displayName(\"Jane S.\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->users->update('user-abc-123', [\n    'display_name' => 'Jane S.',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.users.update(\n  \"user-abc-123\",\n  display_name: \"Jane S.\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Users.UpdateAsync(\"user-abc-123\", new UsersUpdateParams\n{\n    DisplayName = \"Jane S.\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Utilisateur mis à jour. L'enregistrement utilisateur mis à jour complet (même structure que Obtenir l'utilisateur) est renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDetailItem"
                },
                "examples": {
                  "Updated": {
                    "value": {
                      "didit_internal_id": "f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418",
                      "vendor_data": "user-abc-123",
                      "display_name": "Jane S.",
                      "full_name": "Jane Elizabeth Smith",
                      "date_of_birth": "1985-11-22",
                      "effective_name": "Jane S.",
                      "status": "FLAGGED",
                      "metadata": {
                        "tier": "premium"
                      },
                      "portrait_image_url": "https://<media-host>/...",
                      "session_count": 3,
                      "approved_count": 2,
                      "declined_count": 0,
                      "in_review_count": 1,
                      "issuing_states": [
                        "USA"
                      ],
                      "approved_emails": [
                        "john@example.com"
                      ],
                      "approved_phones": [
                        "+14155551234"
                      ],
                      "features": {
                        "ID_VERIFICATION": "Approved",
                        "LIVENESS": "Approved",
                        "FACE_MATCH": "Approved",
                        "AML": "Approved"
                      },
                      "features_list": [
                        {
                          "feature": "ID_VERIFICATION",
                          "status": "Approved"
                        },
                        {
                          "feature": "LIVENESS",
                          "status": "Approved"
                        },
                        {
                          "feature": "FACE_MATCH",
                          "status": "Approved"
                        },
                        {
                          "feature": "AML",
                          "status": "Approved"
                        }
                      ],
                      "last_session_at": "2025-06-15T10:30:00Z",
                      "last_activity_at": "2025-06-15T10:30:00Z",
                      "first_session_at": "2025-06-01T08:00:00Z",
                      "tags": [
                        {
                          "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                          "tag": {
                            "uuid": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
                            "name": "VIP",
                            "color": "#2567FF",
                            "description": null,
                            "source": "custom",
                            "created_at": "2025-05-01T09:00:00Z",
                            "updated_at": "2025-05-01T09:00:00Z"
                          },
                          "added_by_email": "analyst@acme.com",
                          "added_by_name": "Jane Analyst",
                          "created_at": "2025-06-02T11:00:00Z"
                        }
                      ],
                      "comments": [],
                      "created_at": "2025-06-01T08:00:00Z",
                      "updated_at": "2025-06-15T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide — généralement un `status` inconnu ou une `date_of_birth` qui n'est pas au format `YYYY-MM-DD`.",
            "content": {
              "application/json": {
                "examples": {
                  "Bad status": {
                    "value": {
                      "status": [
                        "\"INVALID\" is not a valid choice."
                      ]
                    }
                  },
                  "Bad date_of_birth": {
                    "value": {
                      "date_of_birth": [
                        "Date has wrong format. Use one of these formats instead: YYYY-MM-DD."
                      ]
                    }
                  },
                  "Reason too long": {
                    "value": {
                      "reason": [
                        "Ensure this field has no more than 1000 characters."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Aucun identifiant fourni. Les requêtes vers les chemins `/v3/users/*` sans en-tête `x-api-key` (ou token `Authorization: Bearer`) sont rejetées par le middleware d'authentification avant d'atteindre l'API.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing credentials": {
                    "value": {
                      "detail": "You must be authenticated with a valid access token to access this endpoint."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé ne peut pas mettre à jour les utilisateurs pour cette application. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun utilisateur avec le `vendor_data` fourni n'existe pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "full_name": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 512,
                    "description": "Nom complet de l'utilisateur"
                  },
                  "display_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "Nom d'affichage personnalisé pour cet utilisateur"
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Date de naissance au format YYYY-MM-DD"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "ACTIVE",
                      "FLAGGED",
                      "BLOCKED"
                    ],
                    "description": "Statut du cycle de vie de l'utilisateur. Une modification est enregistrée sous forme d'activité `STATUS_CHANGED`, et `BLOCKED` ajoute les `vendor_data` à la liste de blocage du système (quitter `BLOCKED` supprime cette entrée)."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "Objet JSON arbitraire que vous associez à l'utilisateur. **Remplace complètement** les métadonnées existantes lors de la mise à jour — fusionnez côté client si vous souhaitez uniquement ajouter des clés."
                  },
                  "approved_emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Adresses e-mail vérifiées pour cet utilisateur, par ex. `[\"john@example.com\"]`. Remplace entièrement la liste enregistrée."
                  },
                  "approved_phones": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Numéros de téléphone vérifiés pour cet utilisateur. Remplace entièrement la liste enregistrée."
                  },
                  "issuing_states": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Pays de délivrance (ISO 3166-1 alpha-3), par ex. `[\"USA\"]`. Remplace intégralement la liste stockée."
                  },
                  "reason": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 1000,
                    "description": "Raison pour laquelle le statut a changé. Enregistrée sur l'entrée de changement de statut de l'activité de l'utilisateur (`comments[].comment`, et **Activité** dans la Business Console), uniquement lorsque le statut change réellement. Les webhooks ne la transmettent pas."
                  }
                }
              },
              "examples": {
                "Rename": {
                  "summary": "Définir le nom d'affichage",
                  "value": {
                    "display_name": "Jane S."
                  }
                },
                "Override status": {
                  "summary": "Signaler l'utilisateur pour examen",
                  "value": {
                    "status": "FLAGGED"
                  }
                },
                "Add metadata": {
                  "summary": "Remplacer le JSON des métadonnées",
                  "value": {
                    "metadata": {
                      "tier": "premium",
                      "risk_level": "low"
                    }
                  }
                },
                "Fix extracted DOB": {
                  "summary": "Champs de profil extraits corrects",
                  "value": {
                    "full_name": "Jane Elizabeth Smith",
                    "date_of_birth": "1985-11-22"
                  }
                },
                "Flag with reason": {
                  "summary": "Signaler l'utilisateur et enregistrer le motif",
                  "value": {
                    "status": "FLAGGED",
                    "reason": "Address does not match the billing country"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/users/{vendor_data}/generate-pdf/": {
      "get": {
        "summary": "Télécharger le rapport PDF complet de l'historique utilisateur",
        "description": "Générez et téléchargez un PDF prêt pour la conformité contenant l'historique complet des vérifications de l'utilisateur identifié par `vendor_data`. Il s'agit du même document que celui produit par la Console depuis **User detail → Actions → Download PDF**, afin que les exports périodiques de conformité ne nécessitent plus l'intervention manuelle d'une personne dans la Console.\n\n**Ce que contient le rapport.** Une page de garde avec le récapitulatif du profil (nom, date de naissance, États de délivrance, e-mails et téléphones approuvés), le dernier état de chaque fonctionnalité, les compteurs de sessions et un index des sessions incluses — suivie du rapport standard de chaque session incluse, par ordre chronologique (la plus ancienne en premier). Le rapport de chaque session est le même document que celui renvoyé par `GET /v3/session/{sessionId}/generate-pdf/` pour cette session.\n\n**Sessions éligibles.** Seules les sessions de Vérification des utilisateurs (KYC) avec le statut `Approved`, `Declined`, `In Review` ou `Kyc Expired` sont incluses ; les sessions ayant un autre statut sont ignorées. Si l'utilisateur n'a aucune session dans l'un de ces statuts, l'endpoint renvoie `403` — voir ci-dessous.\n\n**Plafond.** Le rapport est limité aux **20 sessions les plus récentes** pouvant être incluses. Lorsqu'un utilisateur en a davantage, les 20 plus récentes sont intégrées et la page de garde indique combien de sessions plus anciennes ont été omises. Utilisez `GET /v3/sessions/?vendor_data=…` pour obtenir la liste complète au format JSON.\n\n**Personnalisation de marque.** Si votre application dispose d'une personnalisation en marque blanche, la page de garde et chaque rapport de session sont générés avec votre logo et l'URL de votre politique de confidentialité ; sinon, ils portent la marque Didit. Les rapports sont générés en anglais — il n'y a pas de paramètre de langue.\n\n**Aucune mise en cache.** Chaque appel régénère le PDF à partir des données actuelles, de sorte qu'un rapport généré après un examen manuel reflète la décision du réviseur. Deux appels pour le même utilisateur peuvent produire des fichiers aux octets différents — archivez le fichier téléchargé si vous avez besoin d'une copie immuable.\n\n**Latence.** La génération est synchrone et télécharge chaque image stockée de chaque session incluse ; ainsi, le traitement d'un utilisateur ayant de nombreuses sessions riches en médias peut prendre plusieurs dizaines de secondes. Utilisez un délai d'expiration de lecture côté client généreux (120 s recommandées) et enregistrez le flux du corps de la réponse sur le disque. La génération s'interrompt lorsqu'un budget de temps côté serveur est atteint au lieu de s'exécuter jusqu'à ce que votre client abandonne : si ce budget est atteint, la réponse reste un PDF valide contenant les sessions les plus récentes, et la page de garde indique combien ont été omises.\n\n**Portée.** L'utilisateur est résolu au sein de l'application à laquelle appartient la clé API. Une clé ne peut jamais exporter un utilisateur d'une autre application — un tel utilisateur n'existe pas pour elle et l'endpoint renvoie `404`.\n\n**Barre oblique finale.** La route canonique se termine par une barre oblique (`…/generate-pdf/`). Une requête sans cette barre oblique est traitée directement avec la même réponse — il n'y a pas de redirection `301`, de sorte qu'aucun client n'a besoin de suivre les redirections et que `curl` n'a pas besoin de `-L`. Utilisez l'URL avec la barre oblique finale comme dans les exemples.",
        "operationId": "get_user_generate_pdf",
        "x-didit-sdk": {
          "resource": "users",
          "method": "generate_pdf",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "vendor_data",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Votre identifiant unique pour l'utilisateur — chaîne libre (PAS un UUID). Il s'agit de la même valeur que vous avez transmise en tant que `vendor_data` lors de la création des sessions de l'utilisateur, mise en correspondance exactement telle qu'envoyée. Encodez-la au format URL ; une valeur contenant `/` ne peut pas être ciblée par cette route.",
            "example": "user-abc-123"
          }
        ],
        "responses": {
          "200": {
            "description": "Le document PDF généré, renvoyé directement au format binaire `application/pdf` — il n'y a pas d'encapsulation JSON ni d'indirection par URL de téléchargement. Le corps commence par les octets magiques `%PDF`. Enregistrez-le dans un fichier `.pdf` ou transmettez-le en flux continu à votre appelant.",
            "headers": {
              "Content-Disposition": {
                "description": "`attachment; filename=user_{didit_internal_id}.pdf` — le fichier est nommé d'après l'identifiant Didit stable de l'utilisateur (`didit_internal_id` sur `GET /v3/users/{vendor_data}/`), et non d'après `vendor_data`.",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=user_f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418.pdf"
                }
              },
              "Content-Length": {
                "description": "Taille totale du PDF en octets ; le corps n'est pas segmenté.",
                "schema": {
                  "type": "integer",
                  "example": 148213
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Aucun identifiant fourni. Les requêtes vers les chemins `/v3/users/*` sans en-tête `x-api-key` (ou token `Authorization: Bearer`) sont rejetées par le middleware d'authentification avant d'atteindre l'API.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing credentials": {
                    "value": {
                      "detail": "You must be authenticated with a valid access token to access this endpoint."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'autorisation ou d'éligibilité. Distinguez les deux grâce à la chaîne `detail` :\n\n- `\"You do not have permission to perform this action.\"` — la clé API est non valide ou révoquée, ou la requête comporte un token d'utilisateur de la Console au lieu d'une clé API d'application.\n- `\"This user has no sessions in review, declined, approved or kyc expired to report.\"` — l'utilisateur existe dans votre application mais aucune de ses sessions n'est encore dans un statut permettant de générer un rapport (par exemple, chaque session est encore `In Progress`, ou l'utilisateur a été créé via `POST /v3/users/create/` et n'a jamais été vérifié). Attendez un webhook `status.updated` avant de demander le rapport.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "This user has no sessions in review, declined, approved or kyc expired to report."
                    }
                  }
                },
                "examples": {
                  "Invalid credentials": {
                    "summary": "Clé API révoquée ou invalide, ou token d'utilisateur de la console",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "No reportable sessions": {
                    "summary": "L'utilisateur existe mais n'a aucune session Approved / Declined / In Review / Kyc Expired",
                    "value": {
                      "detail": "This user has no sessions in review, declined, approved or kyc expired to report."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun utilisateur avec le `vendor_data` fourni n'existe dans l'application associée à la clé API. Les utilisateurs d'autres applications sont invisibles pour cette clé et renvoient le même `404`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "User not found."
                    }
                  }
                },
                "examples": {
                  "Unknown user": {
                    "summary": "vendor_data ne correspond à aucun utilisateur de cette application",
                    "value": {
                      "detail": "User not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. La génération de PDF fait l'objet d'une limite dédiée de **50 requêtes par minute par identifiant d'authentification** (clé API, token Bearer ou IP source en cas de requête non authentifiée), partagée entre cet endpoint et `GET /v3/session/{sessionId}/generate-pdf/`, en plus de la limite globale de 600 GET/min. Attendez le nombre de secondes indiqué par `Retry-After` (également indiqué dans les en-têtes `X-RateLimit-*`), puis réessayez. Les rapports ne sont pas mis en cache côté serveur, téléchargez donc chaque rapport une seule fois et conservez le fichier au lieu de le récupérer à nouveau.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer la requête.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Nombre maximal de générations de PDF autorisées dans la fenêtre actuelle (50).",
                "schema": {
                  "type": "integer",
                  "example": 50
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Horodatage Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1750000000
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Explication lisible par l'humain du dépassement de la limite de débit.",
                      "example": "Session PDF generation rate limit exceeded. You can make up to 50 requests per minute."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "summary": "Plus de 50 générations de PDF en une minute avec le même identifiant",
                    "value": {
                      "detail": "Session PDF generation rate limit exceeded. You can make up to 50 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --fail \\\n  'https://verification.didit.me/v3/users/user-abc-123/generate-pdf/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  --output user-history.pdf"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.users.generate_pdf(\n    \"user-abc-123\",\n)\nwith open(\"download.pdf\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.users.generatePdf(\"user-abc-123\");\nawait writeFile(\"download.pdf\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.Users.GeneratePDF(ctx, \"user-abc-123\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.users().generatePdf(\"user-abc-123\")\n        .writeTo(Path.of(\"download.pdf\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->users->generatePdf('user-abc-123');\n$content->saveTo('download.pdf');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.users.generate_pdf(\"user-abc-123\")\nFile.binwrite(\"download.pdf\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.Users.GeneratePdfAsync(\"user-abc-123\");\nawait content.SaveToAsync(\"download.pdf\");"
          }
        ]
      }
    },
    "/v3/users/delete/": {
      "post": {
        "summary": "Supprimer des utilisateurs par lot",
        "description": "**Supprimer définitivement** des utilisateurs : les enregistrements utilisateurs sont supprimés de façon permanente. Pour un blocage standard, préférez [Update User Status](#patch-/v3/users/-vendor_data-/update-status/) avec `BLOCKED`. Sélectionnez les utilisateurs avec `vendor_data_list`, avec `didit_internal_id_list`, ou avec les deux à la fois ; ou transmettez `delete_all: true`. Cet endpoint ne restreint jamais `delete_all` avec des filtres. Les filtres Personnes de la Console sont refusés avec un code `400` (voir la réponse `400`), afin qu'une intention ciblée ne se transforme pas en suppression totale. Deux exceptions : `filter_has_approved_sessions` et `filter_has_declined_sessions` ne sont pas refusés et ne sont pas appliqués, donc avec `delete_all: true`, ils suppriment tout de même tous les utilisateurs ; ne les envoyez pas.\n\n**Gabarits biométriques :** à moins que vous ne définissiez `retain_face_embeddings` sur `true`, chaque gabarit biométrique sans image conservé pour ces utilisateurs après la suppression de la session (voir `/v3/biometric-templates/`) est purgé avant la suppression de l'utilisateur, afin que la personne ne corresponde plus dans la détection des doublons et la Recherche faciale. Avec `retain_face_embeddings: true` et `face_retention_days`, vous choisissez de conserver un gabarit biométrique sans image par personne pendant ce nombre de jours, et rien d'autre concernant la personne n'est conservé. Si un gabarit ne peut pas être purgé parce qu'un système de stockage biométrique est indisponible, l'appel renvoie `503`, aucun utilisateur de la requête n'est supprimé, et répéter la requête permet de finaliser l'opération.\n\n**Rapports réglementaires déposés :** si les données sélectionnées figurent dans un rapport réglementaire finalisé, l'ensemble de la requête est refusé avec `409` et rien n'est supprimé. Le corps utilise `code: in_filed_report` et nomme chaque rapport avec `uuid`, `report_number`, `report_type` et `case_uuid`. Supprimez les rapports, puis réessayez la requête.",
        "operationId": "batch_delete_users",
        "x-didit-sdk": {
          "resource": "users",
          "method": "batch_delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Users"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Fournissez `vendor_data_list`, `didit_internal_id_list` ou `delete_all: true`. Les deux listes peuvent être combinées et sont évaluées avec un OU logique (OR). Lorsque `delete_all` est `true`, il a la priorité et les deux listes sont ignorées.",
                "properties": {
                  "vendor_data_list": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Vos propres identifiants à supprimer, mis en correspondance exacte avec ceux transmis."
                  },
                  "didit_internal_id_list": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "Identifiants internes d'utilisateur Didit à supprimer - le `didit_internal_id` renvoyé par les endpoints de création et d'obtention."
                  },
                  "delete_all": {
                    "type": "boolean",
                    "default": false,
                    "description": "Si `true`, supprime tous les utilisateurs de l'application."
                  },
                  "retain_face_embeddings": {
                    "type": "boolean",
                    "default": false,
                    "description": "Votre choix explicite de conserver un gabarit biométrique sans image de chaque personne supprimée pour la détection des doublons, pendant `face_retention_days`. Tout le reste concernant la personne est supprimé. Omettez-le, ou envoyez `false`, pour supprimer les gabarits avec les utilisateurs. Lorsque la valeur est `true`, `face_retention_days` est obligatoire."
                  },
                  "face_retention_days": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 3650,
                    "description": "Nombre de jours pendant lesquels le gabarit biométrique sans image est conservé lorsque `retain_face_embeddings` est `true`. Requis avec ce dernier, et rejeté sans lui avec une erreur `400` sur `face_retention_days`.",
                    "example": 365
                  }
                }
              },
              "examples": {
                "Specific users": {
                  "summary": "Supprimer les utilisateurs par vendor_data",
                  "value": {
                    "vendor_data_list": [
                      "user-123",
                      "user-456"
                    ]
                  }
                },
                "By Didit internal ID": {
                  "summary": "Supprimer les utilisateurs par didit_internal_id",
                  "value": {
                    "didit_internal_id_list": [
                      "3f1c0d3e-8f0a-4c2e-9a3d-9b1f5f4a2c11"
                    ]
                  }
                },
                "All users": {
                  "summary": "Effacer tous les utilisateurs de cette application",
                  "value": {
                    "delete_all": true
                  }
                },
                "Keep face templates": {
                  "summary": "Supprimer les utilisateurs et conserver les modèles faciaux anonymes pendant 365 jours",
                  "value": {
                    "vendor_data_list": [
                      "user-123"
                    ],
                    "retain_face_embeddings": true,
                    "face_retention_days": 365
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/users/delete/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"vendor_data_list\": [\"user-123\", \"user-456\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.users.batch_delete(\n    vendor_data_list=[\"user-123\", \"user-456\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.users.batchDelete({\n  vendor_data_list: [\"user-123\", \"user-456\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Users.BatchDelete(ctx, didit.UsersBatchDeleteParams{\n\tVendorDataList: didit.Some([]string{\"user-123\", \"user-456\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.UsersBatchDeleteParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.users().batchDelete(UsersBatchDeleteParams.builder()\n        .vendorDataList(List.of(\"user-123\", \"user-456\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->users->batchDelete([\n    'vendor_data_list' => ['user-123', 'user-456'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.users.batch_delete(vendor_data_list: [\"user-123\", \"user-456\"])\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Users.BatchDeleteAsync(new UsersBatchDeleteParams\n{\n    VendorDataList = new string[] { \"user-123\", \"user-456\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Utilisateurs supprimés. Renvoie le nombre d'utilisateurs réellement supprimés.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "integer",
                      "description": "Nombre d'utilisateurs supprimés (exclut les valeurs vendor_data qui ne correspondaient à rien)."
                    }
                  }
                },
                "examples": {
                  "Deleted some": {
                    "value": {
                      "deleted": 2
                    }
                  },
                  "Nothing matched": {
                    "value": {
                      "deleted": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation ; rien n'est supprimé. Les erreurs sont indexées par nom de champ. Sans sélecteur (aucune liste et `delete_all` n'étant pas à `true`), le corps est `{\"vendor_data_list\": [\"This field is required unless delete_all is true.\"]}` ; une liste vide est refusée sous sa propre clé avec `\"This list may not be empty.\"`. Un filtre exclusif à la Console (`filter_search`, `filter_status`, `filter_country`, `filter_date_from`, `filter_date_to`, `filter_tag`, `filter_latest_verification_status`, `filter_risk`, `filter_has_sessions`, `filter_has_open_alerts`, `filter_aml_monitoring`, `filter_can_sign_in`, `filter_auth_status`, `filter_auth_method` ou `filter_auth_mfa_enabled`) est refusé dès lors qu'il contient une valeur, même `false`, avec un objet indexé par chacun de ces champs. Toute autre clé `filter_*` inconnue est refusée avec `\"Unknown filter.\"`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing selector": {
                    "summary": "Ni list ni delete_all n'ont été fournis",
                    "value": {
                      "vendor_data_list": [
                        "This field is required unless delete_all is true."
                      ]
                    }
                  },
                  "Console-only filter": {
                    "value": {
                      "filter_has_sessions": "This filter is Console-only and is not supported by this endpoint."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Aucun identifiant fourni. Les requêtes vers les chemins `/v3/users/*` sans en-tête `x-api-key` (ou token `Authorization: Bearer`) sont rejetées par le middleware d'authentification avant d'atteindre l'API.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing credentials": {
                    "value": {
                      "detail": "You must be authenticated with a valid access token to access this endpoint."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API non valide ou révoquée, ou la clé ne peut pas supprimer d'utilisateurs pour cette application. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Un service de stockage biométrique était indisponible lors de la conservation ou de la suppression définitive d'un gabarit biométrique. Rien n'est supprimé ; réitérez la même requête. Les nouvelles tentatives sont idempotentes et convergent vers un seul gabarit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Retryable": {
                    "value": {
                      "detail": "The biometric-template operation could not finish because an external store is unavailable. The operation is retryable."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Rien n'est supprimé. `code` en indique la raison : `in_filed_report` lorsque la sélection inclut une personne présente dans un rapport réglementaire finalisé, `subject_deletion_in_progress` lorsqu'une autre requête est encore en train de supprimer l'une des personnes sélectionnées. Réessayez la requête une fois cette suppression terminée.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/InFiledReportError"
                    },
                    {
                      "$ref": "#/components/schemas/SubjectDeletionInProgressError"
                    }
                  ]
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/sessions/delete/": {
      "post": {
        "summary": "Supprimer des sessions KYC en masse par session_number",
        "description": "Supprimez en masse des sessions de Vérification des utilisateurs (KYC) à partir de leur `session_number` numérique, ou toutes les sessions KYC de votre application avec `delete_all: true`.\n\n`session_number` est le compteur incrémentiel lisible affiché dans la liste des sessions de la Console et renvoyé sous le nom `session_number` par les endpoints de création de session et de décision ; il ne s'agit **pas** de l'UUID `session_id`. Pour supprimer une session par UUID ou pour supprimer une session de Vérification d'entreprise (KYB), que cet endpoint ne traite jamais, utilisez plutôt `DELETE /v3/session/{sessionId}/delete/`.\n\n**Jusqu'à 20 sessions sont supprimées au cours de la requête, au-delà, l'opération s'exécute sous forme de tâche.** Le nombre de sessions correspondantes détermine le comportement, qu'elles soient sélectionnées par `session_numbers` ou avec `delete_all` :\n- Jusqu'à 20 sessions correspondantes : elles sont supprimées avant la réponse, qui est un code `200` avec une entrée par session dans `results[]`.\n- Plus de 20 : la réponse est un code `202` avec une tâche de suppression, et les sessions sont supprimées en arrière-plan. Interrogez régulièrement `GET /v3/sessions/delete/{job_id}/` jusqu'à ce que `status` soit `COMPLETED` ou `FAILED`. Une tâche indique les totaux par résultat, sans jamais préciser quelles sessions elle a supprimées. Une tâche `delete_all` supprime uniquement les sessions créées avant la requête ; les sessions démarrées pendant son exécution ne sont pas supprimées.\n\nChaque session supprimée reçoit exactement le même traitement qu'avec l'endpoint de suppression d'une session unique : la session, chaque tentative de vérification qu'elle contient, sa décision et ses données extraites, ses enregistrements de fonctionnalités associés (vérification d'identité, visage, détection du vivant, correspondance faciale, etc.) ainsi que tous ses fichiers stockés sont supprimés, elle disparaît de tous les endpoints de lecture, et les URL de médias précédemment générées cessent de fonctionner. Les livraisons de webhooks encore en file d'attente pour une session supprimée, ainsi que leurs nouvelles tentatives, sont abandonnées ; les webhooks déjà livrés ne sont pas affectés. Les entrées de la liste de blocage ne sont **pas** supprimées, les crédits déjà consommés ne sont **pas** remboursés, et les entités Utilisateur parentes ne sont **pas** supprimées (utilisez `POST /v3/users/delete/` pour celles-ci) ; aucun webhook n'est émis pour la suppression. La suppression est définitive et irréversible.\n\n**Sémantique de sélection :**\n- Avec `delete_all: true`, vous pouvez restreindre la sélection à l'aide des filtres de `GET /v3/sessions/`, chacun préfixé par `filter_` (par exemple `filter_status`, `filter_workflow_id`, `filter_date_from`). Les filtres acceptant plusieurs valeurs dans List Sessions (`status`, `workflow_id`, `country`, `region`, `document_type`, `document_name`, `session_type`, `warning`, `organization_name`) acceptent une chaîne séparée par des virgules ou un tableau ; les autres prennent une seule valeur. Une valeur vide est ignorée. Les filtres ne s'appliquent qu'avec `delete_all`, et une tâche de suppression applique les mêmes filtres.\n- Une clé `filter_*` inconnue ou une valeur de filtre illisible rejette l'ensemble de la requête avec un code `400` avant que quoi que ce soit ne soit supprimé, évitant ainsi qu'une faute de frappe dans un filtre n'étende la suppression à toutes les sessions.\n- Les entrées de `session_numbers` qui ne correspondent pas à une session KYC active dans votre application (numéros inconnus, sessions déjà supprimées ou sessions appartenant à une autre application) sont **ignorées silencieusement** : elles n'apparaissent pas dans `results` et ne sont pas comptabilisées dans le `total` d'une tâche.\n- Les échecs de validation (une entrée non numérique, une liste vide, ni `session_numbers` ni `delete_all` fourni, ou une conservation de gabarits que l'application ne peut pas honorer) rejettent **l'ensemble de la requête** avec un code `400` et ne suppriment rien.\n- Les sessions sont supprimées par groupes. Si un groupe ne peut pas être supprimé (par exemple parce qu'un service de stockage est indisponible), chaque session de ce groupe est signalée avec `face_retention_outcome: failed_retryable` et reste en place ; les autres groupes ne sont pas affectés. Réitérez la requête pour ces sessions. Une tâche réessaie automatiquement un tel groupe.\n- Il n'y a pas de plafond documenté sur la longueur de la liste ; la limite de débit d'écriture partagée (ci-dessous) constitue la limite pratique.\n\n**Données biométriques faciales :** les champs optionnels `retain_face_embeddings`, `face_retention_days`, `face_retention_deadline`, `deletion_instruction` et `instruction_id` ont la même signification que sur `DELETE /v3/session/{sessionId}/delete/` et s'appliquent à chaque session correspondante. Chaque résultat renvoie son propre `face_retention_outcome`.\n\n**Réponse :** `200 OK` avec `results[]` pour un maximum de 20 sessions correspondantes, ou `202 Accepted` avec une tâche de suppression au-delà. Chaque résultat confirme la suppression, sauf `face_retention_outcome: failed_retryable`, qui signale une session qui n'a PAS été supprimée et doit être réessayée. Les versions antérieures de cet endpoint renvoyaient `204 No Content` ; mettez à jour les clients qui vérifient le code `204`.\n\n**Idempotence :** réitérer la même requête ne supprime rien de plus : les numéros qui ne correspondent plus à une session sont ignorés.\n\n**`delete_all: true` (destructif) :** supprime **chaque** session KYC restante dans l'application ; `session_numbers` est ignoré lorsqu'il est défini. Il n'y a pas d'étape de confirmation ni d'annulation possible.\n\n**Authentification :** clé API dans l'en-tête `x-api-key`. Des identifiants manquants ou invalides renvoient `403` (`{\"detail\": \"You do not have permission to perform this action.\"}`) ; cette API ne renvoie jamais `401`.\n\n**Limite de débit :** budget d'écriture partagé de 300 requêtes/min par clé API sur l'ensemble des endpoints POST/PATCH/DELETE ; tout dépassement renvoie `429`.\n\nCet endpoint accepte uniquement les clés API. Les tokens Bearer utilisateur de la Business Console sont rejetés avec un code `403` (contrairement à la suppression d'une session unique, qui accepte les deux).\n\n**Rapports réglementaires déposés :** si les données sélectionnées figurent dans un rapport réglementaire finalisé, l'ensemble de la requête est refusé avec un code `409` et rien n'est supprimé. Le corps utilise `code: in_filed_report` et nomme chaque rapport avec `uuid`, `report_number`, `report_type` et `case_uuid`. Supprimez les rapports, puis réitérez la requête.",
        "operationId": "batch_delete_sessions",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "batch_delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session_numbers": {
                    "type": "array",
                    "description": "Valeurs numériques `session_number` des sessions KYC à supprimer, sous forme de chaînes composées uniquement de chiffres (les nombres JSON sont également acceptés et convertis). Requis sauf si `delete_all` est `true` ; une liste vide renvoie `400`. Toute entrée ne comportant pas que des chiffres rejette l'ensemble de la requête avec `400` (sauf si `delete_all` est `true`, auquel cas la validation est ignorée et les entrées ne sont pas prises en compte). Les numéros qui ne correspondent à aucune session active dans votre application sont ignorés sans erreur.",
                    "items": {
                      "type": "string",
                      "pattern": "^[0-9]+$",
                      "example": "1001"
                    },
                    "minItems": 1,
                    "example": [
                      "1001",
                      "1002",
                      "1003"
                    ]
                  },
                  "delete_all": {
                    "type": "boolean",
                    "description": "Lorsque la valeur est `true`, toutes les sessions KYC restantes dans l'application appelante sont supprimées et `session_numbers` est ignoré, sauf si vous restreignez la sélection avec les clés `filter_*`. Plus de 20 sessions correspondantes sont traitées sous la forme d'une tâche de suppression (`202`) qui ne couvre que les sessions créées avant la requête. Valeur par défaut : `false`. Irréversible ; il n'y a aucune étape de confirmation.",
                    "default": false,
                    "example": false
                  },
                  "retain_face_embeddings": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Remplacer la `face_retention_policy` de l'application pour cette suppression. `true` conserve un gabarit biométrique facial sans image rattaché à l'utilisateur de la session après la suppression de la session ; `false` supprime l'embedding facial avec la session ; omettez ou définissez sur `null` pour suivre la politique de l'application. Ignoré pour les sessions KYB et pour les sessions sans embedding facial.",
                    "example": true
                  },
                  "face_retention_days": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 3650,
                    "description": "Durée de conservation finie, en jours, pour un gabarit conservé. Requise lorsqu'un gabarit est conservé, sauf si l'application définit déjà `face_retention_days`. La valeur `expires_at` du gabarit correspond à la date d'expiration la plus proche, déterminée par cette durée, la fenêtre générale de conservation des données de l'application et `face_retention_deadline`.",
                    "example": 365
                  },
                  "face_retention_deadline": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Expiration stricte optionnelle pour un modèle conservé. Doit être dans le futur.",
                    "example": "2027-08-28T00:00:00Z"
                  },
                  "deletion_instruction": {
                    "type": "string",
                    "enum": [
                      "operational_session_delete",
                      "privacy_erasure"
                    ],
                    "default": "operational_session_delete",
                    "description": "La catégorie d'instruction que vous donnez. `operational_session_delete` supprime la session et ne conserve un modèle que si la politique ou `retain_face_embeddings` l'indique. `privacy_erasure` purge tout gabarit biométrique conservé ancré à l'Utilisateur de la session avant de supprimer la session, ne peut pas être outrepassé par la politique de l'application, et ne peut pas être combiné avec `retain_face_embeddings: true` (`400`).",
                    "example": "operational_session_delete"
                  },
                  "instruction_id": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Votre référence durable pour cette instruction de suppression (par exemple un ID de ticket d'effacement). Enregistrée dans le journal d'audit et sur tout gabarit conservé. Générée par Didit lorsqu'elle est omise.",
                    "example": "dsar-2026-0142"
                  },
                  "filter_status": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `status` de [Lister les sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "filter_vendor_data": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `vendor_data` de [Lister les sessions](/fr/sessions-api/list-sessions), avec la même valeur. Une seule valeur, pas une liste : un tableau est joint en un seul texte séparé par des virgules, donc plusieurs valeurs ne sont pas traitées comme des alternatives. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "string"
                  },
                  "filter_search": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `search` de [Lister les sessions](/fr/sessions-api/list-sessions), avec la même valeur. Une seule valeur, pas une liste : un tableau est joint en un seul texte séparé par des virgules, donc plusieurs valeurs ne sont pas traitées comme des alternatives. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "string"
                  },
                  "filter_workflow_id": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `workflow_id` de [Lister les sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "filter_date_from": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `date_from` de [List Sessions](/fr/sessions-api/list-sessions), avec la même valeur. Une seule valeur, pas une liste : un tableau est fusionné en une seule valeur séparée par des virgules, donc plusieurs valeurs sont refusées avec `400`. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "string",
                    "format": "date"
                  },
                  "filter_date_to": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `date_to` de [List Sessions](/fr/sessions-api/list-sessions), avec la même valeur. Une seule valeur, pas une liste : un tableau est fusionné en une seule valeur séparée par des virgules, donc plusieurs valeurs sont refusées avec `400`. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "string",
                    "format": "date"
                  },
                  "filter_country": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `country` de [List Sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "filter_document_type": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `document_type` de [List Sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "filter_document_name": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `document_name` de [List Sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "filter_region": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `region` de [Lister les sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "filter_didit_internal_id": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `didit_internal_id` de [List Sessions](/fr/sessions-api/list-sessions), avec la même valeur. Une seule valeur, pas une liste : un tableau est fusionné en une seule valeur séparée par des virgules, donc plusieurs valeurs sont refusées avec `400`. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "string",
                    "format": "uuid"
                  },
                  "filter_session_type": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `session_type` de [Lister les sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "filter_api_service": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `api_service` de [List Sessions](/fr/sessions-api/list-sessions), avec la même valeur. Une seule valeur, pas une liste : un tableau est fusionné en une seule valeur séparée par des virgules, donc plusieurs valeurs sont refusées avec `400`. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "string"
                  },
                  "filter_screened_full_name": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `screened_full_name` de [Lister les sessions](/fr/sessions-api/list-sessions), avec la même valeur. Une seule valeur, pas une liste : un tableau est joint en un seul texte séparé par des virgules, donc plusieurs valeurs ne sont pas traitées comme des alternatives. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "string"
                  },
                  "filter_warning": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `warning` de [Lister les sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "filter_status_initialized_as_in_review": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `status_initialized_as_in_review` de [Lister les sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "boolean"
                  },
                  "filter_is_kyc_to_be_reviewed": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `is_kyc_to_be_reviewed` de [List Sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "boolean"
                  },
                  "filter_euuid": {
                    "description": "Limite un `delete_all` aux sessions correspondant au filtre `euuid` de [List Sessions](/fr/sessions-api/list-sessions), avec la même valeur. Une seule valeur, pas une liste : un tableau est fusionné en une seule valeur séparée par des virgules, donc plusieurs valeurs sont refusées avec `400`. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "type": "string",
                    "format": "uuid"
                  },
                  "filter_organization_name": {
                    "description": "Restreint un `delete_all` aux sessions qui correspondent au filtre `organization_name` de [Lister les sessions](/fr/sessions-api/list-sessions), avec les mêmes valeurs. Une chaîne séparée par des virgules ou un tableau. Avec une clé API, il ne peut correspondre qu'au nom de votre propre organisation, sélectionnant ainsi toutes vos sessions ou aucune. Ignoré sans `delete_all`. Une valeur vide est ignorée et ne restreint pas la sélection.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  }
                }
              },
              "examples": {
                "Specific sessions": {
                  "summary": "Supprimer des sessions spécifiques par numéro",
                  "value": {
                    "session_numbers": [
                      "1001",
                      "1002",
                      "1003"
                    ]
                  }
                },
                "All sessions": {
                  "summary": "Supprimer chaque session KYC de l'application",
                  "value": {
                    "delete_all": true
                  }
                },
                "Delete and retain templates": {
                  "summary": "Supprimer les sessions mais conserver les gabarits biométriques sans image pendant 365 jours",
                  "value": {
                    "session_numbers": [
                      "1001",
                      "1002"
                    ],
                    "retain_face_embeddings": true,
                    "face_retention_days": 365,
                    "instruction_id": "post-approval-cleanup-2026-08"
                  }
                },
                "Privacy erasure": {
                  "summary": "Supprimer les sessions et purger chaque modèle conservé pour leurs Utilisateurs",
                  "value": {
                    "session_numbers": [
                      "1001"
                    ],
                    "deletion_instruction": "privacy_erasure",
                    "instruction_id": "dsar-2026-0142"
                  }
                },
                "Filtered delete_all": {
                  "summary": "Supprimer chaque session Refusée d'un workflow créée en septembre 2026",
                  "value": {
                    "delete_all": true,
                    "filter_status": [
                      "Declined"
                    ],
                    "filter_workflow_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "filter_date_from": "2026-09-01",
                    "filter_date_to": "2026-09-30"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Jusqu'à 20 sessions ont correspondu et ont été traitées dans la requête. Un résultat par session correspondante ; les numéros qui ne correspondent à rien (inconnus ou déjà supprimés) sont ignorés et n'apparaissent pas. Un résultat confirme la suppression sauf lorsque `face_retention_outcome` vaut `failed_retryable` : cette session n'a PAS été supprimée et doit être réessayée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "session_id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "La session supprimée."
                          },
                          "session_number": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Le numéro de la session supprimée."
                          },
                          "face_retention_outcome": {
                            "type": "string",
                            "enum": [
                              "retained_with_user",
                              "deleted",
                              "none",
                              "ineligible_no_vendor_user",
                              "failed_retryable"
                            ],
                            "description": "Ce qui est advenu des données biométriques faciales de la session. `deleted` : l'embedding facial a été supprimé avec la session (par défaut). `retained_with_user` : la session est supprimée et un gabarit biométrique sans image reste rattaché à l'User ; voir `biometric_template_uuid`. `none` : la session ne comportait aucun embedding facial (par exemple une session KYC sur document seul sans selfie de détection du vivant ; les sessions KYB ne sont jamais sélectionnées par cet endpoint). `ineligible_no_vendor_user` : la conservation a été demandée mais la session n'a aucun User lié, l'embedding a donc été supprimé avec la session. `failed_retryable` (endpoint de traitement par lot uniquement) : le groupe avec lequel cette session a été supprimée n'a pas pu être supprimé (un service de stockage, un magasin biométrique ou un fournisseur de surveillance était indisponible) ; cette session est toujours en place, réessayez la requête pour celle-ci."
                          },
                          "biometric_template_uuid": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "Identifiant du gabarit biométrique conservé lorsque `face_retention_outcome` vaut `retained_with_user` ; `null` sinon. Gérez-le via `/v3/biometric-templates/{template_uuid}/`."
                          },
                          "biometric_template_expires_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Moment où le gabarit biométrique conservé est supprimé, lorsque `face_retention_outcome` vaut `retained_with_user` ; `null` lorsqu'aucun gabarit n'est conservé."
                          },
                          "deleted_child_verifications": {
                            "type": "integer",
                            "description": "Toujours `0` sur cet endpoint, qui supprime uniquement les sessions KYC. La suppression d'une session de Vérification d'entreprise (KYB) avec `DELETE /v3/session/{sessionId}/delete/` indique les vérifications créées par celle-ci qui ont été supprimées en même temps."
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Mixed outcomes": {
                    "value": {
                      "results": [
                        {
                          "session_id": "4c5c7f3a-3b1d-4b7e-9c39-2b4f7e6a1d02",
                          "session_number": 1001,
                          "face_retention_outcome": "deleted",
                          "biometric_template_uuid": null,
                          "biometric_template_expires_at": null,
                          "deleted_child_verifications": 0
                        },
                        {
                          "session_id": "b8e1d2c3-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
                          "session_number": 1002,
                          "face_retention_outcome": "retained_with_user",
                          "biometric_template_uuid": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
                          "biometric_template_expires_at": "2027-10-09T10:15:00Z",
                          "deleted_child_verifications": 0
                        },
                        {
                          "session_id": "7a1e9c2d-5f4b-4c3a-8e2d-1b0a9f8e7d6c",
                          "session_number": 1003,
                          "face_retention_outcome": "ineligible_no_vendor_user",
                          "biometric_template_uuid": null,
                          "biometric_template_expires_at": null,
                          "deleted_child_verifications": 0
                        },
                        {
                          "session_id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
                          "session_number": 1004,
                          "face_retention_outcome": "failed_retryable",
                          "biometric_template_uuid": null,
                          "biometric_template_expires_at": null,
                          "deleted_child_verifications": 0
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Plus de 20 sessions correspondent. Elles sont supprimées en arrière-plan ; interrogez `GET /v3/sessions/delete/{job_id}/` jusqu'à ce que `status` soit `COMPLETED` ou `FAILED`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionDeletionJob"
                },
                "examples": {
                  "Job accepted": {
                    "value": {
                      "job_id": "5b8f2c1e-7d3a-4f6b-9e2c-1a0d8f7e6c5b",
                      "status": "PENDING",
                      "total": 250,
                      "processed": 0,
                      "outcomes": {
                        "deleted": 0,
                        "none": 0,
                        "retained_with_user": 0,
                        "ineligible_no_vendor_user": 0,
                        "failed_retryable": 0,
                        "already_deleted": 0
                      },
                      "deleted_child_verifications": 0,
                      "error": null,
                      "created_at": "2026-10-09T10:15:00Z",
                      "completed_at": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — rien n'a été supprimé. Les valeurs d'erreur sont des tableaux de chaînes de message indexés par nom de champ.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_numbers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "additionalProperties": {
                    "description": "Autres clés : une clé `filter_*` qui n'est pas un filtre de List Sessions (`\"Unknown filter.\"`), ou une clé `filter_*` dont la valeur ne peut pas être lue (indexée par cette clé `filter_*`, avec un tableau de messages)."
                  }
                },
                "examples": {
                  "Missing selector": {
                    "summary": "Ni session_numbers ni delete_all n'ont été fournis",
                    "value": {
                      "session_numbers": [
                        "This field is required unless delete_all is true."
                      ]
                    }
                  },
                  "Empty list": {
                    "summary": "session_numbers est un tableau vide",
                    "value": {
                      "session_numbers": [
                        "This list may not be empty."
                      ]
                    }
                  },
                  "Non-numeric entry": {
                    "summary": "session_numbers contient une chaîne non numérique",
                    "value": {
                      "session_numbers": [
                        "All session_numbers must be numeric."
                      ]
                    }
                  },
                  "Privacy erasure cannot retain": {
                    "summary": "deletion_instruction privacy_erasure combinée avec retain_face_embeddings true",
                    "value": {
                      "retain_face_embeddings": [
                        "Privacy erasure cannot retain biometric templates."
                      ]
                    }
                  },
                  "No finite retention duration": {
                    "summary": "Conservation demandée sans face_retention_days sur la requête ou l'application",
                    "value": {
                      "detail": "A finite biometric-template retention duration is required."
                    }
                  },
                  "Unknown filter": {
                    "summary": "Une clé filter_* que List Sessions ne possède pas",
                    "value": {
                      "filter_reviewer": "Unknown filter."
                    }
                  },
                  "Unreadable filter value": {
                    "summary": "Une valeur de filtre qui ne peut pas être lue",
                    "value": {
                      "filter_date_from": [
                        "Enter a valid date."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête x-api-key, ou la clé est invalide",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit d'écriture partagée dépassée (300 requêtes POST/PATCH/DELETE par minute et par clé API). Examinez `Retry-After` et les en-têtes de réponse `X-RateLimit-*` avant de réessayer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget d'écriture épuisé",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Une session sélectionnée fait partie d'un rapport réglementaire finalisé. Rien n'est supprimé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InFiledReportError"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST \\\n  https://verification.didit.me/v3/sessions/delete/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"session_numbers\": [\"1001\", \"1002\", \"1003\"]\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.batch_delete(\n    session_numbers=[\"1001\", \"1002\", \"1003\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.batchDelete({\n  session_numbers: [\"1001\", \"1002\", \"1003\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.BatchDelete(ctx, didit.SessionsBatchDeleteParams{\n\tSessionNumbers: didit.Some([]string{\"1001\", \"1002\", \"1003\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.SessionsBatchDeleteParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().batchDelete(SessionsBatchDeleteParams.builder()\n        .sessionNumbers(List.of(\"1001\", \"1002\", \"1003\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->batchDelete([\n    'session_numbers' => ['1001', '1002', '1003'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.batch_delete(session_numbers: [\"1001\", \"1002\", \"1003\"])\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.BatchDeleteAsync(new SessionsBatchDeleteParams\n{\n    SessionNumbers = new string[] { \"1001\", \"1002\", \"1003\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/sessions/delete/{job_id}/": {
      "get": {
        "summary": "Obtenir une tâche de suppression groupée de sessions",
        "description": "Progression d'une suppression groupée de sessions à laquelle `POST /v3/sessions/delete/` a répondu par `202` (plus de 20 sessions correspondantes, sélectionnées par `session_numbers` ou avec `delete_all`). Interrogez toutes les quelques secondes tant que `status` est `PENDING` ou `PROCESSING` ; arrêtez-vous lorsqu'il passe à `COMPLETED` ou `FAILED`.\n\nLe travail indique le nombre de sessions ayant abouti à chaque résultat et le nombre de sessions qu'il a traitées, mais jamais quelles sessions il a supprimées. Un travail `FAILED` contient la raison dans `error` ; les sessions qu'il n'avait pas encore atteintes sont toujours en place, renouvelez donc la requête de suppression pour les supprimer.\n\n**Authentification :** clé API dans l'en-tête `x-api-key`. Un travail n'est visible que par l'application qui l'a créé ; tout autre `job_id` renvoie `404`. Des identifiants manquants ou invalides renvoient `403` ; cette API ne renvoie jamais `401`.",
        "operationId": "get_session_deletion_job",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "retrieve_deletion_job",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Le `job_id` renvoyé avec la réponse `202` de `POST /v3/sessions/delete/`."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl 'https://verification.didit.me/v3/sessions/delete/JOB_ID/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.retrieve_deletion_job(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.retrieveDeletionJob(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.RetrieveDeletionJob(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().retrieveDeletionJob(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->retrieveDeletionJob('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.retrieve_deletion_job(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.RetrieveDeletionJobAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La tâche.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionDeletionJob"
                },
                "examples": {
                  "Processing": {
                    "value": {
                      "job_id": "5b8f2c1e-7d3a-4f6b-9e2c-1a0d8f7e6c5b",
                      "status": "PROCESSING",
                      "total": 250,
                      "processed": 100,
                      "outcomes": {
                        "deleted": 82,
                        "none": 18,
                        "retained_with_user": 0,
                        "ineligible_no_vendor_user": 0,
                        "failed_retryable": 0,
                        "already_deleted": 0
                      },
                      "deleted_child_verifications": 0,
                      "error": null,
                      "created_at": "2026-10-09T10:15:00Z",
                      "completed_at": null
                    }
                  },
                  "Completed": {
                    "value": {
                      "job_id": "5b8f2c1e-7d3a-4f6b-9e2c-1a0d8f7e6c5b",
                      "status": "COMPLETED",
                      "total": 250,
                      "processed": 250,
                      "outcomes": {
                        "deleted": 204,
                        "none": 44,
                        "retained_with_user": 0,
                        "ineligible_no_vendor_user": 0,
                        "failed_retryable": 0,
                        "already_deleted": 2
                      },
                      "deleted_child_verifications": 0,
                      "error": null,
                      "created_at": "2026-10-09T10:15:00Z",
                      "completed_at": "2026-10-09T10:16:40Z"
                    }
                  },
                  "Failed": {
                    "value": {
                      "job_id": "5b8f2c1e-7d3a-4f6b-9e2c-1a0d8f7e6c5b",
                      "status": "FAILED",
                      "total": 250,
                      "processed": 100,
                      "outcomes": {
                        "deleted": 82,
                        "none": 18,
                        "retained_with_user": 0,
                        "ineligible_no_vendor_user": 0,
                        "failed_retryable": 0,
                        "already_deleted": 0
                      },
                      "deleted_child_verifications": 0,
                      "error": "The deletion stopped before it finished. The sessions it had not reached are still in place; repeat the request to delete them.",
                      "created_at": "2026-10-09T10:15:00Z",
                      "completed_at": "2026-10-09T10:15:52Z"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête x-api-key, ou la clé est invalide",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune tâche de suppression avec ce `job_id` n'existe pour l'application appelante. Les tâches ne sont visibles que par l'application qui les a créées."
          }
        }
      }
    },
    "/v3/sessions/{session_id}/reviews/": {
      "get": {
        "summary": "Lister les examens de session et le journal d'activité",
        "description": "Renvoie le journal d'audit / fil d'activité pour une session de Vérification des utilisateurs (KYC), du plus récent au plus ancien, dans une enveloppe paginée (`count` / `next` / `previous` / `results`, 50 entrées par page par défaut).\n\nLes entrées du fil sont générées par chaque intervenant interagissant avec la session : les décisions manuelles prises via `PATCH /v3/session/{session_id}/update-status/` (qui enregistre `previous_status` → `new_status`), l'activité des réviseurs dans la Console (commentaires avec mentions `@email`, modifications de données KYC/POA, téléversements/suppressions de fichiers, changements de tags, consultations de la page de détails), les correspondances de surveillance continue AML et les notes ajoutées via `POST` sur ce même chemin. La lecture de ce fil est l'équivalent côté API du panneau **Activité** dans la vue de session de la Console Didit.\n\nSeules les sessions de Vérification des utilisateurs (KYC) sont accessibles ici ; les identifiants de session de Vérification d'entreprise (KYB) renvoient `404`.",
        "operationId": "list_session_reviews",
        "x-didit-sdk": {
          "resource": "sessions.reviews",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification des utilisateurs (KYC). Doit appartenir à la même application que la clé API — les UUID inter-applications, les sessions supprimées et les identifiants de session de Vérification d'entreprise (KYB) renvoient tous `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Taille de page. Vaut `50` par défaut.",
            "schema": {
              "type": "integer",
              "default": 50,
              "example": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Nombre d'entrées à ignorer depuis le début du flux (ordonné). Vaut `0` par défaut. Les URL `next` / `previous` dans la réponse contiennent les bonnes valeurs pour parcourir le flux.",
            "schema": {
              "type": "integer",
              "default": 0,
              "example": 0
            }
          },
          {
            "name": "ordering",
            "in": "query",
            "required": false,
            "description": "Ordre de tri. Le flux est défini par défaut sur le plus récent en premier (`-created_at`) ; transmettez `created_at` pour le lire du plus ancien au plus récent. Les valeurs inconnues sont ignorées sans avertissement (l'ordre par défaut est appliqué) ; d'autres noms de champs de sérialiseur sont également acceptés.",
            "schema": {
              "type": "string",
              "default": "-created_at",
              "example": "created_at"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Flux d'activité paginé, du plus récent au plus ancien par défaut. `count` est le nombre total d'entrées ; `next` / `previous` sont des URL de page prêtes à l'emploi (`null` aux extrémités). Un `count` de `0` avec des `results` vides indique qu'aucune activité n'a encore été enregistrée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre total d'entrées de flux pour cette session (toutes pages confondues).",
                      "example": 3
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL de la page suivante, ou `null` sur la dernière page.",
                      "example": null
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL de la page précédente, ou `null` sur la première page.",
                      "example": null
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReviewItem"
                      },
                      "description": "Entrées de flux pour cette page."
                    }
                  }
                },
                "examples": {
                  "DecisionTrail": {
                    "summary": "Approbation manuelle accompagnée de notes ajoutées par l'API",
                    "value": {
                      "count": 3,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "de0561bc-5583-4409-9171-1a31a4c8a5f4",
                          "activity_type": "STATUS_UPDATED",
                          "actor_display": "API Client",
                          "actor_email": null,
                          "actor_type": "API_KEY",
                          "new_status": "Approved",
                          "previous_status": "In Review",
                          "comment": "Document re-checked manually; address matches.",
                          "mentioned_emails": [],
                          "previous_value": {
                            "status": "In Review"
                          },
                          "new_value": {
                            "status": "Approved"
                          },
                          "changed_fields": [
                            "status"
                          ],
                          "metadata": null,
                          "created_at": "2026-06-12T00:19:31.918735Z"
                        },
                        {
                          "uuid": "35370f58-5098-44ee-8a06-8c9af80b2455",
                          "activity_type": "STATUS_UPDATED",
                          "actor_display": "Unknown",
                          "actor_email": null,
                          "actor_type": "CONSOLE_USER",
                          "new_status": null,
                          "previous_status": null,
                          "comment": "Note without status.",
                          "mentioned_emails": [],
                          "previous_value": null,
                          "new_value": null,
                          "changed_fields": [],
                          "metadata": null,
                          "created_at": "2026-06-12T00:18:44.504157Z"
                        },
                        {
                          "uuid": "00338f82-f1c5-4f57-8614-c49bb258af1a",
                          "activity_type": "STATUS_UPDATED",
                          "actor_display": "Unknown",
                          "actor_email": null,
                          "actor_type": "CONSOLE_USER",
                          "new_status": "In Review",
                          "previous_status": null,
                          "comment": "Flagging for manual document re-check.",
                          "mentioned_emails": [],
                          "previous_value": null,
                          "new_value": null,
                          "changed_fields": [],
                          "metadata": null,
                          "created_at": "2026-06-12T00:18:44.466537Z"
                        }
                      ]
                    }
                  },
                  "PaginatedFirstPage": {
                    "summary": "Première page avec limit=2 — le champ next contient l'URL de suivi",
                    "value": {
                      "count": 4,
                      "next": "https://verification.didit.me/v3/sessions/8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d/reviews/?limit=2&offset=2",
                      "previous": null,
                      "results": [
                        {
                          "uuid": "de0561bc-5583-4409-9171-1a31a4c8a5f4",
                          "activity_type": "STATUS_UPDATED",
                          "actor_display": "API Client",
                          "actor_email": null,
                          "actor_type": "API_KEY",
                          "new_status": "Approved",
                          "previous_status": "In Review",
                          "comment": "Document re-checked manually; address matches.",
                          "mentioned_emails": [],
                          "previous_value": {
                            "status": "In Review"
                          },
                          "new_value": {
                            "status": "Approved"
                          },
                          "changed_fields": [
                            "status"
                          ],
                          "metadata": null,
                          "created_at": "2026-06-12T00:19:31.918735Z"
                        },
                        {
                          "uuid": "bd4e6227-bdd2-42b2-a726-1d12f785a457",
                          "activity_type": "STATUS_UPDATED",
                          "actor_display": "Unknown",
                          "actor_email": null,
                          "actor_type": "CONSOLE_USER",
                          "new_status": null,
                          "previous_status": null,
                          "comment": null,
                          "mentioned_emails": [],
                          "previous_value": null,
                          "new_value": null,
                          "changed_fields": [],
                          "metadata": null,
                          "created_at": "2026-06-12T00:18:44.540238Z"
                        }
                      ]
                    }
                  },
                  "Empty": {
                    "summary": "Session sans activité enregistrée pour le moment",
                    "value": {
                      "count": 0,
                      "next": null,
                      "previous": null,
                      "results": []
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`x-api-key` manquant, malformé, expiré ou révoqué. L'authentification est vérifiée avant la recherche de la session, donc une clé manquante renvoie `403` même lorsque l'UUID de session n'existe pas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "You do not have permission to perform this action."
                    }
                  }
                },
                "examples": {
                  "InvalidKey": {
                    "summary": "En-tête x-api-key manquant ou invalide",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session de vérification des utilisateurs (KYC) avec cet UUID n'est visible pour votre application : l'UUID n'existe pas, la session a été supprimée ou elle appartient à une autre application. Les ID de session de vérification d'entreprise (KYB) renvoient également `404` ici — le flux des examens n'est accessible que pour les sessions KYC.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Session not found."
                    }
                  }
                },
                "examples": {
                  "NotFound": {
                    "summary": "UUID de session inconnu, supprimé ou appartenant à une autre application",
                    "value": {
                      "detail": "Session not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Examinez les en-têtes de réponse `Retry-After` et `X-RateLimit-*`. Voir [Limitation de débit](/fr/integration/rate-limiting)."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -s 'https://verification.didit.me/v3/sessions/8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d/reviews/?limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.sessions.reviews.list(\n    \"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.sessions.reviews.list(\"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Sessions.Reviews.ListAutoPaging(ctx, \"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\", didit.SessionsReviewsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.sessions().reviews().list(\"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->sessions->reviews->list('8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.sessions.reviews.list(\"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Sessions.Reviews.ListAsync(\"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "summary": "Ajouter une note d'examen au journal d'audit d'une session",
        "description": "Ajoute une note au fil d'activité / d'examen d'une session de Vérification des utilisateurs (KYC). **Cet endpoint enregistre uniquement une entrée — il ne modifie jamais la session.** Le `status` de la session reste intact, aucune validation de transition de statut n'est exécutée et aucun webhook n'est déclenché. Pour réellement approuver, refuser ou rouvrir une session (ce qui écrit également une entrée `STATUS_UPDATED` entièrement attribuée dans ce fil), utilisez plutôt `PATCH /v3/session/{session_id}/update-status/`.\n\nLes deux champs du corps sont facultatifs et un objet JSON vide est accepté. `new_status` est enregistré purement comme un libellé sur l'entrée et accepte l'une des dix valeurs de statut de session (sensible à la casse). Les mentions `@email` à l'intérieur de `comment` sont enregistrées sous forme de texte brut uniquement — elles ne déclenchent aucune notification sur cet endpoint, et le champ `mentioned_emails` de l'entrée reste vide.\n\nRemarque sur l'attribution : les entrées créées ici ne comportent aucune information sur l'acteur. Dans le fil, elles affichent `actor_display: \"Unknown\"`, `actor_type: \"CONSOLE_USER\"` et `activity_type: \"STATUS_UPDATED\"` (valeurs de stockage par défaut), et le champ `user` du corps `201` est `\"Unknown\"`.",
        "operationId": "create_session_review",
        "x-didit-sdk": {
          "resource": "sessions.reviews",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": false,
            "description": "Définir sur `application/json` lors de l'envoi d'un corps JSON.",
            "schema": {
              "type": "string",
              "example": "application/json"
            }
          },
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification des utilisateurs (KYC). Doit appartenir à la même application que la clé API — les UUID inter-applications, les sessions supprimées et les identifiants de session de Vérification d'entreprise (KYB) renvoient tous `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "new_status": {
                    "type": "string",
                    "nullable": true,
                    "enum": [
                      "Not Started",
                      "In Progress",
                      "Approved",
                      "Declined",
                      "In Review",
                      "Expired",
                      "Abandoned",
                      "Kyc Expired",
                      "Resubmitted",
                      "Awaiting User"
                    ],
                    "description": "Libellé de statut optionnel à enregistrer sur l'entrée. Accepte toute valeur de statut de session, sensible à la casse (`\"approved\"` est rejeté avec `400`). Enregistrer un statut ici ne modifie **pas** le statut réel de la session — utilisez l'endpoint de mise à jour du statut pour cela.",
                    "example": "In Review"
                  },
                  "comment": {
                    "type": "string",
                    "nullable": true,
                    "description": "Note en texte libre optionnelle (aucune limite de longueur imposée). Stockée textuellement ; les mentions `@email` ne sont pas traitées sur cet endpoint.",
                    "example": "Flagging for manual document re-check."
                  }
                }
              },
              "examples": {
                "NoteWithStatusLabel": {
                  "summary": "Note portant un label de statut (statut de session inchangé)",
                  "value": {
                    "new_status": "In Review",
                    "comment": "Flagging for manual document re-check."
                  }
                },
                "CommentOnly": {
                  "summary": "Note simple sans étiquette de statut",
                  "value": {
                    "comment": "Customer emailed an updated utility bill; awaiting upload."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Entrée enregistrée dans le journal d'audit de la session. La session elle-même reste inchangée — son `status` conserve sa valeur précédente et aucun webhook n'est envoyé. La nouvelle entrée apparaît également en tête de `GET …/reviews/` (avec `actor_display: \"Unknown\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "type": "string",
                      "description": "Nom d'affichage de l'auteur de l'entrée. Toujours `\"Unknown\"` pour les entrées créées via cet endpoint, car il n'enregistre aucune attribution d'acteur.",
                      "example": "Unknown"
                    },
                    "new_status": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "Not Started",
                        "In Progress",
                        "Approved",
                        "Declined",
                        "In Review",
                        "Expired",
                        "Abandoned",
                        "Kyc Expired",
                        "Resubmitted",
                        "Awaiting User"
                      ],
                      "description": "Le libellé de statut enregistré sur l'entrée, ou `null` si aucun n'a été transmis. Le statut réel de la session n'est pas affecté.",
                      "example": "In Review"
                    },
                    "comment": {
                      "type": "string",
                      "nullable": true,
                      "description": "La note enregistrée sur l'entrée, ou `null` si aucune n'a été envoyée.",
                      "example": "Flagging for manual document re-check."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Date et heure d'écriture de l'entrée, ISO 8601 UTC.",
                      "example": "2026-06-12T00:18:44.466537Z"
                    }
                  }
                },
                "examples": {
                  "NoteWithStatusLabel": {
                    "summary": "Note avec un label de statut",
                    "value": {
                      "user": "Unknown",
                      "new_status": "In Review",
                      "comment": "Flagging for manual document re-check.",
                      "created_at": "2026-06-12T00:18:44.466537Z"
                    }
                  },
                  "CommentOnly": {
                    "summary": "Note simple",
                    "value": {
                      "user": "Unknown",
                      "new_status": null,
                      "comment": "Note without status.",
                      "created_at": "2026-06-12T00:18:44.504157Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation, renvoyée sous la forme d'une table de messages par champ. La cause habituelle est une valeur de `new_status` qui ne fait pas partie des dix statuts autorisés — la vérification est sensible à la casse.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "new_status": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "\"approved\" is not a valid choice."
                      ]
                    }
                  }
                },
                "examples": {
                  "InvalidStatusChoice": {
                    "summary": "Valeur de statut en minuscules / inconnue",
                    "value": {
                      "new_status": [
                        "\"approved\" is not a valid choice."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`x-api-key` manquant, malformé, expiré ou révoqué. L'authentification est vérifiée avant la recherche de la session, donc une clé manquante renvoie `403` même lorsque l'UUID de session n'existe pas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "You do not have permission to perform this action."
                    }
                  }
                },
                "examples": {
                  "InvalidKey": {
                    "summary": "En-tête x-api-key manquant ou invalide",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session de vérification des utilisateurs (KYC) avec cet UUID n'est visible pour votre application : l'UUID n'existe pas, la session a été supprimée ou elle appartient à une autre application. Les ID de session de vérification d'entreprise (KYB) renvoient également `404` ici — le flux des examens n'est accessible que pour les sessions KYC.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Session not found."
                    }
                  }
                },
                "examples": {
                  "NotFound": {
                    "summary": "UUID de session inconnu, supprimé ou appartenant à une autre application",
                    "value": {
                      "detail": "Session not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Examinez les en-têtes de réponse `Retry-After` et `X-RateLimit-*`. Voir [Limitation de débit](/fr/integration/rate-limiting)."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "# Records an audit-trail note only -- the session's status does NOT change.\ncurl -s -X POST https://verification.didit.me/v3/sessions/8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d/reviews/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"new_status\": \"In Review\",\n    \"comment\": \"Flagging for manual document re-check.\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.reviews.create(\n    \"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\",\n    new_status=\"In Review\",\n    comment=\"Flagging for manual document re-check.\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.reviews.create(\"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\", {\n  new_status: \"In Review\",\n  comment: \"Flagging for manual document re-check.\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Reviews.Create(ctx, \"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\", didit.SessionsReviewsCreateParams{\n\tNewStatus: didit.Some(didit.SessionsReviewsCreateParamsNewStatus(\"In Review\")),\n\tComment:   didit.String(\"Flagging for manual document re-check.\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsReviewsCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().reviews().create(\"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\", SessionsReviewsCreateParams.builder()\n        .newStatus(SessionsReviewsCreateParams.NewStatus.of(\"In Review\"))\n        .comment(\"Flagging for manual document re-check.\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->reviews->create('8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d', [\n    'new_status' => 'In Review',\n    'comment' => 'Flagging for manual document re-check.',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.reviews.create(\n  \"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\",\n  new_status: \"In Review\",\n  comment: \"Flagging for manual document re-check.\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Reviews.CreateAsync(\"8c2f3a14-7e9b-4d23-9e83-3f7d5e8a1c6d\", new SessionsReviewsCreateParams\n{\n    NewStatus = new SessionsReviewsCreateParamsNewStatus(\"In Review\"),\n    Comment = \"Flagging for manual document re-check.\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/billing/balance/": {
      "get": {
        "summary": "Obtenir le solde de crédits",
        "description": "Obtenir le solde actuel de crédits prépayés en USD (à l'échelle de l'organisation) ainsi que la configuration de recharge automatique. Les montants sont des chaînes décimales — analysez-les avec une bibliothèque décimale.",
        "operationId": "get_billing_balance",
        "x-didit-sdk": {
          "resource": "billing",
          "method": "retrieve_balance",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Billing"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/billing/balance/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.billing.retrieve_balance()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.billing.retrieveBalance();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Billing.RetrieveBalance(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.billing().retrieveBalance();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->billing->retrieveBalance();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.billing.retrieve_balance\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Billing.RetrieveBalanceAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Solde de crédits actuel ainsi que la configuration de recharge automatique de l'organisation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "balance",
                    "auto_refill_enabled"
                  ],
                  "properties": {
                    "balance": {
                      "type": "string",
                      "description": "Solde de crédits prépayés actuel en USD, sous forme de chaîne décimale à virgule fixe. Diminue au fur et à mesure que les vérifications sont facturées et augmente lorsqu'une recharge est finalisée."
                    },
                    "auto_refill_enabled": {
                      "type": "boolean",
                      "description": "Lorsque la valeur est `true`, Didit débitera automatiquement le moyen de paiement enregistré pour ajouter des crédits dès que le solde franchit `auto_refill_threshold`. Configuré depuis Console → Facturation."
                    },
                    "auto_refill_amount": {
                      "type": "string",
                      "nullable": true,
                      "description": "Montant en USD qui sera débité et ajouté au solde à chaque recharge automatique, à sa valeur nominale. À définir entre \\$50 et \\$20,000 dans Console → Facturation. `null` lorsque la recharge automatique est désactivée ou non configurée."
                    },
                    "auto_refill_threshold": {
                      "type": "string",
                      "nullable": true,
                      "description": "Seuil de déclenchement en USD. Le rechargement automatique se déclenche lorsque `balance` descend en dessous de cette valeur. `null` lorsque le rechargement automatique est désactivé ou non configuré."
                    }
                  }
                },
                "examples": {
                  "Healthy balance with auto-refill": {
                    "value": {
                      "balance": "1234.5600",
                      "auto_refill_enabled": true,
                      "auto_refill_amount": "500.00",
                      "auto_refill_threshold": "100.00"
                    }
                  },
                  "Low balance, manual top-up only": {
                    "value": {
                      "balance": "12.0000",
                      "auto_refill_enabled": false,
                      "auto_refill_amount": null,
                      "auto_refill_threshold": null
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas lire les données de facturation pour cette organisation. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/billing/top-up/": {
      "post": {
        "summary": "Recharger des crédits",
        "description": "Ajoutez des crédits via une session Stripe Checkout hébergée (**\\$50 à \\$20,000** par recharge). Les recharges sont disponibles pour les forfaits Free, Growth et Scale, ajoutées à leur valeur nominale sans réduction ni bonus, et sont valables 12 mois ; les contrats annuels Enterprise ne peuvent pas effectuer de recharge. Redirigez le client vers la `checkout_session_url` retournée.",
        "operationId": "billing_top_up",
        "x-didit-sdk": {
          "resource": "billing",
          "method": "top_up",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Billing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_in_dollars"
                ],
                "properties": {
                  "amount_in_dollars": {
                    "type": "number",
                    "minimum": 50,
                    "maximum": 20000,
                    "description": "Montant à débiter, en USD. **Doit être compris entre 50 et 20,000.** Le solde reçoit le même montant, sans réduction ni bonus. La taxe est ajoutée automatiquement lors du paiement en fonction de l'adresse de facturation du client."
                  },
                  "success_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL vers laquelle le paiement hébergé redirige le client après un paiement réussi. Actuellement défini par défaut sur `https://console.didit.me`. Transmettez explicitement une URL fonctionnelle ; l'hôte par défaut n'est pas disponible. Ajoutez l'espace réservé textuel `{CHECKOUT_SESSION_ID}` si vous souhaitez que le paiement hébergé remplace l'identifiant de session."
                  },
                  "cancel_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL vers laquelle le paiement hébergé redirige le client lorsqu'il abandonne ou ferme la fenêtre Checkout. Actuellement défini par défaut sur `https://console.didit.me`. Transmettez explicitement une URL fonctionnelle ; l'hôte par défaut n'est pas disponible."
                  }
                }
              },
              "examples": {
                "Minimum top-up": {
                  "value": {
                    "amount_in_dollars": 50
                  }
                },
                "Custom amount with redirects": {
                  "value": {
                    "amount_in_dollars": 500,
                    "success_url": "https://yourapp.com/billing/top-up/success",
                    "cancel_url": "https://yourapp.com/billing/top-up/cancel"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/billing/top-up/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"amount_in_dollars\": 500,\n    \"success_url\": \"https://yourapp.com/billing/success\",\n    \"cancel_url\": \"https://yourapp.com/billing/cancel\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.billing.top_up(\n    amount_in_dollars=50.0,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.billing.topUp({\n  amount_in_dollars: 50.0,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Billing.TopUp(ctx, didit.BillingTopUpParams{\n\tAmountInDollars: 50.0,\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.BillingTopUpParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.billing().topUp(BillingTopUpParams.builder()\n        .amountInDollars(50.0)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->billing->topUp([\n    'amount_in_dollars' => 50.0,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.billing.top_up(amount_in_dollars: 50.0)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Billing.TopUpAsync(new BillingTopUpParams\n{\n    AmountInDollars = 50.0,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Session de paiement hébergée créée. Redirigez l'utilisateur vers `checkout_session_url` pour finaliser le paiement.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "checkout_session_id",
                    "checkout_session_url"
                  ],
                  "properties": {
                    "checkout_session_id": {
                      "type": "string",
                      "description": "Identifiant de la session de paiement hébergée (par exemple `cs_test_a1B2c3...`). Utile pour la réconciliation côté serveur."
                    },
                    "checkout_session_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "URL à usage unique d'une page de paiement hébergée. Redirigez le client ici pour effectuer le paiement."
                    }
                  }
                },
                "examples": {
                  "Created": {
                    "value": {
                      "checkout_session_id": "cs_test_a1B2c3D4e5F6g7H8i9J0",
                      "checkout_session_url": "https://checkout.example.com/c/pay/cs_test_a1B2c3D4e5F6g7H8i9J0"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Payload non valide : le montant est manquant, n'est pas un nombre, est inférieur au minimum de \\$50 ou supérieur au maximum de \\$20,000, ou l'organisation est sous contrat annuel Enterprise. Le corps de l'erreur est un tableau JSON.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing amount": {
                    "value": [
                      "amount_in_dollars is required."
                    ]
                  },
                  "Not a number": {
                    "value": [
                      "amount_in_dollars must be a number."
                    ]
                  },
                  "Below minimum": {
                    "value": [
                      "Amount must be at least $50."
                    ]
                  },
                  "Above maximum": {
                    "value": [
                      "Amount must be at most $20,000."
                    ]
                  },
                  "Annual plan": {
                    "value": [
                      "You have an annual plan. Contact your account manager to top up."
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas créer de sessions de recharge pour cette organisation. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/webhook/destinations/": {
      "get": {
        "summary": "Lister les destinations de webhook",
        "description": "Lister toutes les destinations de webhook (tableau non paginé, les plus anciennes en premier). Chaque élément contient la configuration de la destination, ses métriques de livraison pour les 30 derniers jours (`metrics_window_days`) avec une entrée `daily_points` par jour, ainsi que son état (`health_status`, `failing_streak`, `failing_since`, `last_success_at`). La liste n'a pas d'objet `summary` et n'inclut jamais le secret de signature : chaque élément n'affiche que `secret_last4`. Récupérez une destination unique (`GET /v3/webhook/destinations/{destination_uuid}/`) pour lire `secret_shared_key`.",
        "operationId": "list_webhook_destinations",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/webhook/destinations/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.destinations.list()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.destinations.list();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Webhooks.Destinations.List(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().destinations().list();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->destinations->list();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.webhooks.destinations.list.each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.Destinations.ListAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des destinations de webhook (non paginée, de la plus ancienne à la plus récente).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "uuid": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Identifiant stable de la destination ; à utiliser comme `{destination_uuid}` pour la mise à jour ou la suppression."
                      },
                      "label": {
                        "type": "string",
                        "description": "Nom lisible par l'humain affiché dans la Console."
                      },
                      "url": {
                        "type": "string",
                        "format": "uri",
                        "description": "URL de destination qui reçoit les requêtes `POST` avec le payload du webhook."
                      },
                      "enabled": {
                        "type": "boolean",
                        "description": "Lorsque la valeur est `false`, Didit ignore silencieusement la livraison vers cette destination."
                      },
                      "webhook_version": {
                        "type": "string",
                        "enum": [
                          "v1",
                          "v2",
                          "v3"
                        ],
                        "description": "Version du schéma de payload envoyée à cette destination. `v3` est le format actuel/recommandé."
                      },
                      "subscribed_events": {
                        "$ref": "#/components/schemas/WebhookSubscribedEvents"
                      },
                      "subscribed_events_count": {
                        "type": "integer",
                        "description": "Longueur en cache de `subscribed_events`, utile pour le rendu de l'interface utilisateur."
                      },
                      "deliveries_count": {
                        "type": "integer",
                        "description": "Tentatives de livraison (nouvelles tentatives incluses) effectuées vers cette destination au cours des 30 derniers jours."
                      },
                      "failed_deliveries_count": {
                        "type": "integer",
                        "description": "Tentatives de livraison au cours des 30 derniers jours auxquelles la destination a répondu par HTTP 400 ou plus, ou n'a pas répondu (délai d'attente dépassé, connexion refusée ou adresse bloquée)."
                      },
                      "average_response_time_ms": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Temps de réponse moyen en millisecondes au cours des 30 derniers jours, arrondi à l'entier le plus proche. `null` s'il n'y a eu aucune livraison pendant cette période."
                      },
                      "error_rate_percentage": {
                        "type": "integer",
                        "description": "`round(failed_deliveries_count / deliveries_count * 100)` sur les 30 derniers jours ; `0` lorsqu'il n'y a aucune livraison."
                      },
                      "last_delivery_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Horodatage de la tentative de livraison la plus récente (succès ou échec). `null` si aucune livraison n'a été effectuée."
                      },
                      "metrics_window_days": {
                        "type": "integer",
                        "description": "Durée en jours de la fenêtre couverte par `deliveries_count`, `failed_deliveries_count`, `average_response_time_ms`, `error_rate_percentage` et `daily_points`. Toujours `30`."
                      },
                      "health_status": {
                        "type": "string",
                        "enum": [
                          "healthy",
                          "degraded",
                          "failing"
                        ],
                        "description": "État de la livraison. `failing` : 3 événements consécutifs ou plus ont échoué lors de leur première tentative de livraison depuis la dernière réponse réussie de la destination (voir `failing_streak`). `degraded` : pas en échec, mais une tentative de livraison a échoué au cours des dernières 24 heures et aucune tentative ultérieure n'a livré cet événement ; une nouvelle tentative ou un renvoi qui le livre efface cet état. `healthy` : aucun des deux. Indépendant de `enabled`. Une tentative échouée correspond à une réponse HTTP 400 ou supérieure, ou à une absence totale de réponse."
                      },
                      "failing_streak": {
                        "type": "integer",
                        "description": "Nombre d'événements consécutifs dont la première tentative de livraison a échoué depuis la dernière réponse réussie de la destination, au cours des 30 derniers jours. Les nouvelles tentatives ne sont pas comptabilisées, et toute tentative réussie, y compris une nouvelle tentative ou un renvoi, met fin à la série. `0` lorsqu'aucun événement n'a échoué depuis le dernier succès."
                      },
                      "failing_since": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Date et heure de la première tentative infructueuse de la série d'échecs en cours (`failing_streak`). `null` lorsque `failing_streak` vaut `0`."
                      },
                      "last_success_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Date et heure auxquelles la destination a répondu pour la dernière fois à une livraison avec un statut HTTP inférieur à 400, au cours des 30 derniers jours. `null` si ce n'est pas le cas dans cet intervalle."
                      },
                      "environment": {
                        "type": "string",
                        "enum": [
                          "live",
                          "sandbox"
                        ],
                        "description": "Environnement de l'application propriétaire de la destination."
                      },
                      "daily_points": {
                        "type": "array",
                        "description": "Une entrée par jour UTC des 30 derniers jours, de la plus ancienne à la plus récente, y compris les jours sans aucune livraison. Prend en compte chaque tentative, nouvelles tentatives incluses.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "date": {
                              "type": "string",
                              "format": "date",
                              "description": "Le jour UTC."
                            },
                            "total_deliveries": {
                              "type": "integer",
                              "description": "Tentatives de livraison effectuées ce jour-là."
                            },
                            "failed_deliveries": {
                              "type": "integer",
                              "description": "Tentatives effectuées ce jour-là ayant reçu une réponse HTTP 400 ou supérieure, ou n'ayant reçu aucune réponse."
                            }
                          }
                        }
                      },
                      "secret_last4": {
                        "type": "string",
                        "description": "Quatre derniers caractères du secret de signature actuel de la destination, vous permettant de distinguer les secrets. Insuffisant pour vérifier une signature."
                      },
                      "created_by_email": {
                        "type": "string",
                        "nullable": true,
                        "description": "E-mail du membre de la Business Console qui a créé la destination. `null` pour une destination créée avec une clé API."
                      },
                      "created_by_name": {
                        "type": "string",
                        "nullable": true,
                        "description": "Nom du membre de la Business Console ayant créé la destination. `null` pour une destination créée avec une clé API."
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "updated_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    }
                  }
                },
                "examples": {
                  "Two destinations": {
                    "value": [
                      {
                        "uuid": "11111111-2222-3333-4444-555555555555",
                        "label": "Production session webhooks",
                        "url": "https://yourapp.com/webhooks/didit",
                        "enabled": true,
                        "webhook_version": "v3",
                        "subscribed_events": [
                          "status.updated",
                          "data.updated"
                        ],
                        "subscribed_events_count": 2,
                        "deliveries_count": 12453,
                        "failed_deliveries_count": 14,
                        "average_response_time_ms": 187,
                        "error_rate_percentage": 0,
                        "last_delivery_at": "2026-05-17T09:21:18Z",
                        "metrics_window_days": 30,
                        "health_status": "healthy",
                        "failing_streak": 0,
                        "failing_since": null,
                        "last_success_at": "2026-05-17T09:21:18Z",
                        "environment": "live",
                        "daily_points": [
                          {
                            "date": "2026-04-18",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-19",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-20",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-21",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-22",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-23",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-24",
                            "total_deliveries": 415,
                            "failed_deliveries": 9
                          },
                          {
                            "date": "2026-04-25",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-26",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-27",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-28",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-29",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-30",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-01",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-02",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-03",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-04",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-05",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-06",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-07",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-08",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-09",
                            "total_deliveries": 415,
                            "failed_deliveries": 5
                          },
                          {
                            "date": "2026-05-10",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-11",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-12",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-13",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-14",
                            "total_deliveries": 415,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-15",
                            "total_deliveries": 416,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-16",
                            "total_deliveries": 416,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-17",
                            "total_deliveries": 416,
                            "failed_deliveries": 0
                          }
                        ],
                        "secret_last4": "0xnQ",
                        "created_by_email": null,
                        "created_by_name": null,
                        "created_at": "2026-01-04T08:00:00Z",
                        "updated_at": "2026-04-22T14:09:11Z"
                      },
                      {
                        "uuid": "22222222-3333-4444-5555-666666666666",
                        "label": "Staging mirror",
                        "url": "https://staging.yourapp.com/webhooks/didit",
                        "enabled": false,
                        "webhook_version": "v3",
                        "subscribed_events": [
                          "status.updated"
                        ],
                        "subscribed_events_count": 1,
                        "deliveries_count": 0,
                        "failed_deliveries_count": 0,
                        "average_response_time_ms": null,
                        "error_rate_percentage": 0,
                        "last_delivery_at": null,
                        "metrics_window_days": 30,
                        "health_status": "healthy",
                        "failing_streak": 0,
                        "failing_since": null,
                        "last_success_at": null,
                        "environment": "live",
                        "daily_points": [
                          {
                            "date": "2026-04-18",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-19",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-20",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-21",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-22",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-23",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-24",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-25",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-26",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-27",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-28",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-29",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-04-30",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-01",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-02",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-03",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-04",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-05",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-06",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-07",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-08",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-09",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-10",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-11",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-12",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-13",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-14",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-15",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-16",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          },
                          {
                            "date": "2026-05-17",
                            "total_deliveries": 0,
                            "failed_deliveries": 0
                          }
                        ],
                        "secret_last4": "k9Qe",
                        "created_by_email": "reviewer@example.com",
                        "created_by_name": "Example Reviewer",
                        "created_at": "2026-03-12T10:15:02Z",
                        "updated_at": "2026-03-12T10:15:02Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer une destination de webhook",
        "description": "Créez une destination de webhook. La réponse inclut le secret de signature HMAC `secret_shared_key` généré automatiquement (également consultable ultérieurement via `GET /v3/webhook/destinations/{destination_uuid}/`). Envoyez toujours `subscribed_events` avec au moins un événement (aucun caractère générique) : une liste explicitement vide est rejetée avec une erreur 400, et omettre ce champ crée une destination abonnée à rien, qui ne reçoit jamais de webhook. La paire `(application, url)` doit être unique parmi les destinations de l'application.",
        "operationId": "create_webhook_destination",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/webhook/destinations/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"label\": \"Production session webhooks\",\n    \"url\": \"https://yourapp.com/webhooks/didit\",\n    \"webhook_version\": \"v3\",\n    \"subscribed_events\": [\"status.updated\", \"data.updated\"]\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.destinations.create(\n    label=\"Production session webhooks\",\n    url=\"https://yourapp.com/webhooks/didit\",\n    webhook_version=\"v3\",\n    subscribed_events=[\"status.updated\", \"data.updated\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.destinations.create({\n  label: \"Production session webhooks\",\n  url: \"https://yourapp.com/webhooks/didit\",\n  webhook_version: \"v3\",\n  subscribed_events: [\"status.updated\", \"data.updated\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Webhooks.Destinations.Create(ctx, didit.WebhooksDestinationsCreateParams{\n\tLabel:            \"Production session webhooks\",\n\tURL:              \"https://yourapp.com/webhooks/didit\",\n\tWebhookVersion:   didit.Some(didit.WebhooksDestinationsCreateParamsWebhookVersion(\"v3\")),\n\tSubscribedEvents: didit.Some([]didit.WebhookEvent{didit.WebhookEvent(\"status.updated\"), didit.WebhookEvent(\"data.updated\")}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.WebhookEvent;\nimport me.didit.types.WebhooksDestinationsCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().destinations().create(WebhooksDestinationsCreateParams.builder()\n        .label(\"Production session webhooks\")\n        .url(\"https://yourapp.com/webhooks/didit\")\n        .webhookVersion(WebhooksDestinationsCreateParams.WebhookVersion.of(\"v3\"))\n        .subscribedEvents(List.of(WebhookEvent.of(\"status.updated\"), WebhookEvent.of(\"data.updated\")))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->destinations->create([\n    'label' => 'Production session webhooks',\n    'url' => 'https://yourapp.com/webhooks/didit',\n    'webhook_version' => 'v3',\n    'subscribed_events' => ['status.updated', 'data.updated'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.webhooks.destinations.create(\n  label: \"Production session webhooks\",\n  url: \"https://yourapp.com/webhooks/didit\",\n  webhook_version: \"v3\",\n  subscribed_events: [\"status.updated\", \"data.updated\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.Destinations.CreateAsync(new WebhooksDestinationsCreateParams\n{\n    Label = \"Production session webhooks\",\n    Url = \"https://yourapp.com/webhooks/didit\",\n    WebhookVersion = new WebhooksDestinationsCreateParamsWebhookVersion(\"v3\"),\n    SubscribedEvents = new WebhookEvent[] { \"status.updated\", \"data.updated\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "label",
                  "url"
                ],
                "properties": {
                  "label": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom lisible par l'humain affiché dans Console → Webhooks. Permet de distinguer les destinations lorsque vous en avez plusieurs (par ex. \"Prod\", \"Staging mirror\")."
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL HTTPS qui recevra les requêtes `POST`. Doit être unique parmi les destinations de l'application. Utilisez un endpoint stable et renforcé : Didit réessaie les livraisons ayant échoué selon un calendrier d'intervalles progressifs.",
                    "maxLength": 2000
                  },
                  "enabled": {
                    "type": "boolean",
                    "default": true,
                    "description": "Lorsque la valeur est `false`, la destination est enregistrée mais Didit n'y enverra aucun webhook. Pratique pour les configurations de staging que vous souhaitez laisser en attente."
                  },
                  "webhook_version": {
                    "type": "string",
                    "enum": [
                      "v1",
                      "v2",
                      "v3"
                    ],
                    "description": "Version du schéma de payload que Didit enverra. `v3` est le format actuel/recommandé ; les versions antérieures sont conservées pour des raisons de rétrocompatibilité avec les intégrations historiques."
                  },
                  "subscribed_events": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/WebhookSubscribedEvents"
                      }
                    ],
                    "description": "Événements à livrer. Concrètement obligatoire : un `[]` explicite est rejeté avec une erreur 400, et omettre ce champ crée une destination sans aucun abonnement qui ne reçoit rien."
                  }
                }
              },
              "examples": {
                "session_updates": {
                  "summary": "Mises à jour du statut et des données de la session",
                  "value": {
                    "label": "Production session webhooks",
                    "url": "https://yourapp.com/webhooks/didit",
                    "webhook_version": "v3",
                    "subscribed_events": [
                      "status.updated",
                      "data.updated"
                    ]
                  }
                },
                "transaction_updates": {
                  "summary": "Mises à jour de la surveillance des transactions",
                  "value": {
                    "label": "Transaction monitoring webhooks",
                    "url": "https://yourapp.com/webhooks/didit-transactions",
                    "webhook_version": "v3",
                    "subscribed_events": [
                      "transaction.created",
                      "transaction.status.updated"
                    ]
                  }
                },
                "entity_updates": {
                  "summary": "Mises à jour des entités Utilisateur et Entreprise",
                  "value": {
                    "label": "Entity lifecycle webhooks",
                    "url": "https://yourapp.com/webhooks/didit-entities",
                    "webhook_version": "v3",
                    "subscribed_events": [
                      "user.status.updated",
                      "user.data.updated",
                      "business.status.updated",
                      "business.data.updated",
                      "activity.created"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Destination créée. `secret_shared_key` est le secret de signature HMAC — stockez-le maintenant.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant stable de la destination. À utiliser comme `{destination_uuid}` dans les appels ultérieurs."
                    },
                    "label": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "webhook_version": {
                      "type": "string",
                      "enum": [
                        "v1",
                        "v2",
                        "v3"
                      ]
                    },
                    "secret_shared_key": {
                      "type": "string",
                      "description": "Secret de signature HMAC généré automatiquement et lié à cette destination (token de 43 caractères compatible URL). Utilisez-le pour vérifier les en-têtes de signature sur les webhooks entrants. Toujours renvoyé en intégralité aux appelants utilisant une clé API ; les utilisateurs de la Console doivent disposer de l'autorisation `read:webhooks`, faute de quoi ils verront une chaîne vide."
                    },
                    "secret_last4": {
                      "type": "string",
                      "description": "Quatre derniers caractères du secret de signature actuel de la destination, vous permettant de distinguer les secrets. Insuffisant pour vérifier une signature."
                    },
                    "previous_secret_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Défini pendant 24 heures après la rotation du secret de signature de la destination dans la Business Console. Jusqu'à cette échéance, chaque livraison vers la destination comporte également `X-Signature-Previous`, `X-Signature-V2-Previous` et `X-Signature-Simple-Previous`, générés avec le secret remplacé (voir [Vérification de signature](/fr/integration/webhooks#vérification-de-la-signature)). `null` si aucune rotation n'a eu lieu au cours des dernières 24 heures."
                    },
                    "subscribed_events": {
                      "$ref": "#/components/schemas/WebhookSubscribedEvents"
                    },
                    "created_by_email": {
                      "type": "string",
                      "nullable": true,
                      "description": "E-mail du membre de la Business Console qui a créé la destination. `null` pour une destination créée avec une clé API."
                    },
                    "created_by_name": {
                      "type": "string",
                      "nullable": true,
                      "description": "Nom du membre de la Business Console ayant créé la destination. `null` pour une destination créée avec une clé API."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "health_status": {
                      "type": "string",
                      "enum": [
                        "healthy",
                        "degraded",
                        "failing"
                      ],
                      "description": "État de la livraison. `failing` : 3 événements consécutifs ou plus ont échoué lors de leur première tentative de livraison depuis la dernière réponse réussie de la destination (voir `failing_streak`). `degraded` : pas en échec, mais une tentative de livraison a échoué au cours des dernières 24 heures et aucune tentative ultérieure n'a livré cet événement ; une nouvelle tentative ou un renvoi qui le livre efface cet état. `healthy` : aucun des deux. Indépendant de `enabled`. Une tentative échouée correspond à une réponse HTTP 400 ou supérieure, ou à une absence totale de réponse."
                    },
                    "failing_streak": {
                      "type": "integer",
                      "description": "Nombre d'événements consécutifs dont la première tentative de livraison a échoué depuis la dernière réponse réussie de la destination, au cours des 30 derniers jours. Les nouvelles tentatives ne sont pas comptabilisées, et toute tentative réussie, y compris une nouvelle tentative ou un renvoi, met fin à la série. `0` lorsqu'aucun événement n'a échoué depuis le dernier succès."
                    },
                    "failing_since": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Date et heure de la première tentative infructueuse de la série d'échecs en cours (`failing_streak`). `null` lorsque `failing_streak` vaut `0`."
                    },
                    "last_success_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Date et heure auxquelles la destination a répondu pour la dernière fois à une livraison avec un statut HTTP inférieur à 400, au cours des 30 derniers jours. `null` si ce n'est pas le cas dans cet intervalle."
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "live",
                        "sandbox"
                      ],
                      "description": "Environnement de l'application propriétaire de la destination."
                    },
                    "summary": {
                      "type": "object",
                      "description": "Métriques de livraison pour les derniers `metrics_window_days` (30) jours. `last_delivery_at` correspond à la tentative la plus récente, quelle que soit la date à laquelle elle a été effectuée.",
                      "properties": {
                        "total_deliveries": {
                          "type": "integer"
                        },
                        "failed_deliveries": {
                          "type": "integer"
                        },
                        "error_rate_percentage": {
                          "type": "integer"
                        },
                        "min_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "avg_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "max_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "last_delivery_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "metrics_window_days": {
                          "type": "integer",
                          "description": "Durée en jours de la fenêtre couverte par les autres métriques récapitulatives. Toujours `30`."
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Created": {
                    "value": {
                      "uuid": "11111111-2222-3333-4444-555555555555",
                      "label": "Production session webhooks",
                      "url": "https://yourapp.com/webhooks/didit",
                      "enabled": true,
                      "webhook_version": "v3",
                      "secret_shared_key": "tno2NTeRC1ZK3sBOYlBJDyEzBVENl3pQ1AcZyAW0xnQ",
                      "secret_last4": "0xnQ",
                      "previous_secret_expires_at": null,
                      "subscribed_events": [
                        "status.updated",
                        "data.updated"
                      ],
                      "created_by_email": null,
                      "created_by_name": null,
                      "created_at": "2026-05-17T10:00:00Z",
                      "updated_at": "2026-05-17T10:00:00Z",
                      "health_status": "healthy",
                      "failing_streak": 0,
                      "failing_since": null,
                      "last_success_at": null,
                      "environment": "live",
                      "summary": {
                        "total_deliveries": 0,
                        "failed_deliveries": 0,
                        "error_rate_percentage": 0,
                        "min_response_time_ms": null,
                        "avg_response_time_ms": null,
                        "max_response_time_ms": null,
                        "last_delivery_at": null,
                        "metrics_window_days": 30
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Échec de la validation — généralement une URL en doublon, `subscribed_events` manquant/non valide ou un nom d'événement inconnu.",
            "content": {
              "application/json": {
                "examples": {
                  "Duplicate URL": {
                    "value": {
                      "url": [
                        "This webhook destination already exists for the application."
                      ]
                    }
                  },
                  "Empty events list": {
                    "value": {
                      "subscribed_events": [
                        "At least one subscribed event is required."
                      ]
                    }
                  },
                  "Unknown event": {
                    "value": {
                      "subscribed_events": [
                        "Unsupported webhook events: foo.bar"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/webhook/destinations/{destination_uuid}/": {
      "get": {
        "summary": "Obtenir la destination de webhook",
        "description": "Récupérer une destination de webhook avec son secret de signature `secret_shared_key`, son état (`health_status`, `failing_streak`, `failing_since`, `last_success_at`) et un récapitulatif des livraisons `summary` pour les 30 derniers jours. Les appelants par clé API reçoivent toujours le secret complet ; les utilisateurs de la Console sans `read:webhooks` voient une chaîne vide.",
        "operationId": "get_webhook_destination",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "name": "destination_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la destination (le `uuid` renvoyé par la création / le listage).",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/webhook/destinations/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.destinations.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.destinations.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Webhooks.Destinations.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().destinations().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->destinations->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.webhooks.destinations.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.Destinations.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détails de la destination de webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "label": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "webhook_version": {
                      "type": "string",
                      "enum": [
                        "v1",
                        "v2",
                        "v3"
                      ]
                    },
                    "secret_shared_key": {
                      "type": "string",
                      "description": "Secret de signature HMAC (token de 43 caractères compatible avec les URL). Toujours renvoyé dans son intégralité aux appelants utilisant une clé API ; les utilisateurs de la console ont besoin de l'autorisation `read:webhooks`, sinon une chaîne vide est renvoyée."
                    },
                    "secret_last4": {
                      "type": "string",
                      "description": "Quatre derniers caractères du secret de signature actuel de la destination, vous permettant de distinguer les secrets. Insuffisant pour vérifier une signature."
                    },
                    "previous_secret_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Défini pendant 24 heures après la rotation du secret de signature de la destination dans la Business Console. Jusqu'à cette échéance, chaque livraison vers la destination comporte également `X-Signature-Previous`, `X-Signature-V2-Previous` et `X-Signature-Simple-Previous`, générés avec le secret remplacé (voir [Vérification de signature](/fr/integration/webhooks#vérification-de-la-signature)). `null` si aucune rotation n'a eu lieu au cours des dernières 24 heures."
                    },
                    "subscribed_events": {
                      "$ref": "#/components/schemas/WebhookSubscribedEvents"
                    },
                    "created_by_email": {
                      "type": "string",
                      "nullable": true,
                      "description": "E-mail du membre de la Business Console qui a créé la destination. `null` pour une destination créée avec une clé API."
                    },
                    "created_by_name": {
                      "type": "string",
                      "nullable": true,
                      "description": "Nom du membre de la Business Console ayant créé la destination. `null` pour une destination créée avec une clé API."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "health_status": {
                      "type": "string",
                      "enum": [
                        "healthy",
                        "degraded",
                        "failing"
                      ],
                      "description": "État de la livraison. `failing` : 3 événements consécutifs ou plus ont échoué lors de leur première tentative de livraison depuis la dernière réponse réussie de la destination (voir `failing_streak`). `degraded` : pas en échec, mais une tentative de livraison a échoué au cours des dernières 24 heures et aucune tentative ultérieure n'a livré cet événement ; une nouvelle tentative ou un renvoi qui le livre efface cet état. `healthy` : aucun des deux. Indépendant de `enabled`. Une tentative échouée correspond à une réponse HTTP 400 ou supérieure, ou à une absence totale de réponse."
                    },
                    "failing_streak": {
                      "type": "integer",
                      "description": "Nombre d'événements consécutifs dont la première tentative de livraison a échoué depuis la dernière réponse réussie de la destination, au cours des 30 derniers jours. Les nouvelles tentatives ne sont pas comptabilisées, et toute tentative réussie, y compris une nouvelle tentative ou un renvoi, met fin à la série. `0` lorsqu'aucun événement n'a échoué depuis le dernier succès."
                    },
                    "failing_since": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Date et heure de la première tentative infructueuse de la série d'échecs en cours (`failing_streak`). `null` lorsque `failing_streak` vaut `0`."
                    },
                    "last_success_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Date et heure auxquelles la destination a répondu pour la dernière fois à une livraison avec un statut HTTP inférieur à 400, au cours des 30 derniers jours. `null` si ce n'est pas le cas dans cet intervalle."
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "live",
                        "sandbox"
                      ],
                      "description": "Environnement de l'application propriétaire de la destination."
                    },
                    "summary": {
                      "type": "object",
                      "description": "Métriques de livraison pour les derniers `metrics_window_days` (30) jours. `last_delivery_at` correspond à la tentative la plus récente, quelle que soit la date à laquelle elle a été effectuée.",
                      "properties": {
                        "total_deliveries": {
                          "type": "integer"
                        },
                        "failed_deliveries": {
                          "type": "integer"
                        },
                        "error_rate_percentage": {
                          "type": "integer"
                        },
                        "min_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "avg_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "max_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "last_delivery_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "metrics_window_days": {
                          "type": "integer",
                          "description": "Durée en jours de la fenêtre couverte par les autres métriques récapitulatives. Toujours `30`."
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Healthy destination": {
                    "value": {
                      "uuid": "11111111-2222-3333-4444-555555555555",
                      "label": "Production session webhooks",
                      "url": "https://yourapp.com/webhooks/didit",
                      "enabled": true,
                      "webhook_version": "v3",
                      "secret_shared_key": "tno2NTeRC1ZK3sBOYlBJDyEzBVENl3pQ1AcZyAW0xnQ",
                      "secret_last4": "0xnQ",
                      "previous_secret_expires_at": null,
                      "subscribed_events": [
                        "status.updated",
                        "data.updated"
                      ],
                      "created_by_email": null,
                      "created_by_name": null,
                      "created_at": "2026-01-04T08:00:00Z",
                      "updated_at": "2026-04-22T14:09:11Z",
                      "health_status": "healthy",
                      "failing_streak": 0,
                      "failing_since": null,
                      "last_success_at": "2026-05-17T09:21:18Z",
                      "environment": "live",
                      "summary": {
                        "total_deliveries": 12453,
                        "failed_deliveries": 14,
                        "error_rate_percentage": 0,
                        "min_response_time_ms": 41,
                        "avg_response_time_ms": 187,
                        "max_response_time_ms": 2103,
                        "last_delivery_at": "2026-05-17T09:21:18Z",
                        "metrics_window_days": 30
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune destination avec cet UUID n'existe, ou elle appartient à une autre application, ou elle a été supprimée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Webhook destination not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour la destination de webhook",
        "description": "Mettre à jour une destination de webhook. **`subscribed_events` est REMPLACÉ dans son intégralité, et non fusionné** : récupérez d'abord, ajoutez, puis renvoyez. Le secret n'est pas renouvelé. Tout `uuid` dans le corps est ignoré : le chemin indique la destination.",
        "operationId": "update_webhook_destination",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "name": "destination_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la destination à mettre à jour.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "description": "Nouveau nom lisible par un humain."
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Nouvelle URL cible. Doit être unique au sein de l'application."
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "Définir sur `false` pour suspendre les livraisons vers cette destination sans la supprimer."
                  },
                  "webhook_version": {
                    "type": "string",
                    "enum": [
                      "v1",
                      "v2",
                      "v3"
                    ],
                    "description": "Nouvelle version du schéma de payload pour les livraisons futures."
                  },
                  "subscribed_events": {
                    "$ref": "#/components/schemas/WebhookSubscribedEvents"
                  }
                }
              },
              "examples": {
                "Pause destination": {
                  "value": {
                    "enabled": false
                  }
                },
                "Add transaction events": {
                  "value": {
                    "subscribed_events": [
                      "status.updated",
                      "data.updated",
                      "transaction.created",
                      "transaction.status.updated"
                    ]
                  }
                },
                "Move target URL": {
                  "value": {
                    "label": "Production session webhooks v2",
                    "url": "https://api.yourapp.com/webhooks/didit/v2"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/webhook/destinations/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"subscribed_events\": [\n      \"status.updated\",\n      \"data.updated\",\n      \"transaction.created\"\n    ]\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.destinations.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    enabled=False,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.destinations.update(\"11111111-2222-3333-4444-555555555555\", {\n  enabled: false,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Webhooks.Destinations.Update(ctx, \"11111111-2222-3333-4444-555555555555\", didit.WebhooksDestinationsUpdateParams{\n\tEnabled: didit.Bool(false),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.WebhooksDestinationsUpdateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().destinations().update(\"11111111-2222-3333-4444-555555555555\", WebhooksDestinationsUpdateParams.builder()\n        .enabled(false)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->destinations->update('11111111-2222-3333-4444-555555555555', [\n    'enabled' => false,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.webhooks.destinations.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  enabled: false\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.Destinations.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", new WebhooksDestinationsUpdateParams\n{\n    Enabled = false,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Destination de webhook mise à jour. Le corps a la même forme que `GET /v3/webhook/destinations/{destination_uuid}/`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "label": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "webhook_version": {
                      "type": "string",
                      "enum": [
                        "v1",
                        "v2",
                        "v3"
                      ]
                    },
                    "secret_shared_key": {
                      "type": "string"
                    },
                    "secret_last4": {
                      "type": "string",
                      "description": "Quatre derniers caractères du secret de signature actuel de la destination, vous permettant de distinguer les secrets. Insuffisant pour vérifier une signature."
                    },
                    "previous_secret_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Défini pendant 24 heures après la rotation du secret de signature de la destination dans la Business Console. Jusqu'à cette échéance, chaque livraison vers la destination comporte également `X-Signature-Previous`, `X-Signature-V2-Previous` et `X-Signature-Simple-Previous`, générés avec le secret remplacé (voir [Vérification de signature](/fr/integration/webhooks#vérification-de-la-signature)). `null` si aucune rotation n'a eu lieu au cours des dernières 24 heures."
                    },
                    "subscribed_events": {
                      "$ref": "#/components/schemas/WebhookSubscribedEvents"
                    },
                    "created_by_email": {
                      "type": "string",
                      "nullable": true,
                      "description": "E-mail du membre de la Business Console qui a créé la destination. `null` pour une destination créée avec une clé API."
                    },
                    "created_by_name": {
                      "type": "string",
                      "nullable": true,
                      "description": "Nom du membre de la Business Console ayant créé la destination. `null` pour une destination créée avec une clé API."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "health_status": {
                      "type": "string",
                      "enum": [
                        "healthy",
                        "degraded",
                        "failing"
                      ],
                      "description": "État de la livraison. `failing` : 3 événements consécutifs ou plus ont échoué lors de leur première tentative de livraison depuis la dernière réponse réussie de la destination (voir `failing_streak`). `degraded` : pas en échec, mais une tentative de livraison a échoué au cours des dernières 24 heures et aucune tentative ultérieure n'a livré cet événement ; une nouvelle tentative ou un renvoi qui le livre efface cet état. `healthy` : aucun des deux. Indépendant de `enabled`. Une tentative échouée correspond à une réponse HTTP 400 ou supérieure, ou à une absence totale de réponse."
                    },
                    "failing_streak": {
                      "type": "integer",
                      "description": "Nombre d'événements consécutifs dont la première tentative de livraison a échoué depuis la dernière réponse réussie de la destination, au cours des 30 derniers jours. Les nouvelles tentatives ne sont pas comptabilisées, et toute tentative réussie, y compris une nouvelle tentative ou un renvoi, met fin à la série. `0` lorsqu'aucun événement n'a échoué depuis le dernier succès."
                    },
                    "failing_since": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Date et heure de la première tentative infructueuse de la série d'échecs en cours (`failing_streak`). `null` lorsque `failing_streak` vaut `0`."
                    },
                    "last_success_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Date et heure auxquelles la destination a répondu pour la dernière fois à une livraison avec un statut HTTP inférieur à 400, au cours des 30 derniers jours. `null` si ce n'est pas le cas dans cet intervalle."
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "live",
                        "sandbox"
                      ],
                      "description": "Environnement de l'application propriétaire de la destination."
                    },
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total_deliveries": {
                          "type": "integer"
                        },
                        "failed_deliveries": {
                          "type": "integer"
                        },
                        "error_rate_percentage": {
                          "type": "integer"
                        },
                        "min_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "avg_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "max_response_time_ms": {
                          "type": "integer",
                          "nullable": true
                        },
                        "last_delivery_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "metrics_window_days": {
                          "type": "integer",
                          "description": "Durée en jours de la fenêtre couverte par les autres métriques récapitulatives. Toujours `30`."
                        }
                      },
                      "description": "Métriques de livraison pour les derniers `metrics_window_days` (30) jours. `last_delivery_at` correspond à la tentative la plus récente, quelle que soit la date à laquelle elle a été effectuée."
                    }
                  }
                },
                "examples": {
                  "Paused": {
                    "value": {
                      "uuid": "11111111-2222-3333-4444-555555555555",
                      "label": "Production session webhooks",
                      "url": "https://yourapp.com/webhooks/didit",
                      "enabled": false,
                      "webhook_version": "v3",
                      "secret_shared_key": "tno2NTeRC1ZK3sBOYlBJDyEzBVENl3pQ1AcZyAW0xnQ",
                      "secret_last4": "0xnQ",
                      "previous_secret_expires_at": null,
                      "subscribed_events": [
                        "status.updated",
                        "data.updated"
                      ],
                      "created_by_email": null,
                      "created_by_name": null,
                      "created_at": "2026-01-04T08:00:00Z",
                      "updated_at": "2026-05-17T11:02:55Z",
                      "health_status": "healthy",
                      "failing_streak": 0,
                      "failing_since": null,
                      "last_success_at": "2026-05-17T09:21:18Z",
                      "environment": "live",
                      "summary": {
                        "total_deliveries": 12453,
                        "failed_deliveries": 14,
                        "error_rate_percentage": 0,
                        "min_response_time_ms": 41,
                        "avg_response_time_ms": 187,
                        "max_response_time_ms": 2103,
                        "last_delivery_at": "2026-05-17T09:21:18Z",
                        "metrics_window_days": 30
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Échec de validation (URL en double, liste d'événements vide ou inconnue, corps malformé).",
            "content": {
              "application/json": {
                "examples": {
                  "Duplicate URL": {
                    "value": {
                      "url": [
                        "This webhook destination already exists for the application."
                      ]
                    }
                  },
                  "Empty events": {
                    "value": {
                      "subscribed_events": [
                        "At least one subscribed event is required."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La destination avec cet UUID n'existe pas (ou est supprimée, ou appartient à une autre application).",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Webhook destination not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Supprimer la destination de webhook",
        "description": "Supprimer définitivement une destination de webhook, son secret de signature et l'intégralité de son journal de livraison. Cette action est irréversible. Aucun nouveau webhook n'est envoyé à l'URL de la destination ; les autres destinations abonnées aux mêmes événements continuent de les recevoir. Par la suite, la destination n'apparaît plus dans `GET /v3/webhook/destinations/`, et chaque route sous `/v3/webhook/destinations/{destination_uuid}/`, y compris ses livraisons, le détail d'une livraison et son renvoi, renvoie 404. L'ancien champ `webhook_url` de l'application est défini sur l'URL de la plus ancienne destination activée restante, ou effacé lorsqu'il ne reste aucune destination activée. Appeler DELETE à nouveau renvoie 404.",
        "operationId": "delete_webhook_destination",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "name": "destination_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la destination à supprimer.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/webhook/destinations/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.webhooks.destinations.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.webhooks.destinations.delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.Webhooks.Destinations.Delete(ctx, \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.webhooks().destinations().delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->webhooks->destinations->delete('11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.webhooks.destinations.delete(\"11111111-2222-3333-4444-555555555555\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.Webhooks.Destinations.DeleteAsync(\"11111111-2222-3333-4444-555555555555\");"
          }
        ],
        "responses": {
          "204": {
            "description": "Destination, secret de signature et journal de livraison supprimés définitivement. Aucun corps de réponse."
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune destination avec cet UUID n'existe pour l'application (déjà supprimée ou n'a jamais existé).",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Webhook destination not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/wallet-screening/": {
      "post": {
        "summary": "Filtrer une adresse",
        "description": "Exécuter un filtrage AML à la demande pour un portefeuille/adresse crypto unique sans créer de transaction. Résout le fournisseur d'analyse blockchain configuré de votre application, filtre l'adresse de manière synchrone et renvoie le résultat de risque normalisé. LIGHTNING est disponible uniquement avec une connexion BYOK Elliptic ou Chainalysis ajoutée via le Marketplace. Rien n'est écrit dans la table des transactions. Une utilisation de surveillance AML est facturée par filtrage réussi (les applications en sandbox ne sont pas facturées).",
        "operationId": "screenWallet",
        "x-didit-sdk": {
          "resource": "wallet_screening",
          "method": "screen",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "wallet_address"
                ],
                "properties": {
                  "wallet_address": {
                    "type": "string",
                    "description": "L'adresse crypto ou l'identifiant réseau à soumettre au filtrage. Doit correspondre au réseau sélectionné (par ex. une adresse de 40 caractères hexadécimaux préfixée par `0x` pour les chaînes EVM). Alias : `address`.",
                    "example": "0x94f1b9b64e2932f6a2db338f616844400cd58e8a"
                  },
                  "blockchain": {
                    "type": "string",
                    "description": "Identifiant de réseau optionnel. En cas d'omission, le réseau est déduit du format de l'adresse : les adresses `bc1`, `1` et `3` correspondent à Bitcoin (BTC), les adresses `T` à Tron (TRX) et les clés publiques en base58 à Solana (SOL). Une adresse `0x` est valide sur tous les réseaux EVM ; omettre `blockchain` pour celle-ci renvoie une réponse 422 avec les réseaux candidats dans `candidate_chains`. Le filtrage géré prend en charge BTC, ETH, LTC, XRP, BCH, DOGE, TRX, SOL, MATIC, BNB, BASE (Base), OP (Optimism), ARB (Arbitrum One), AVAX (Avalanche C-Chain), ADA (Cardano), XLM (Stellar) et HBAR (Hedera). USDT et USDC sont des alias Ethereum historiques, et non des recherches multiréseaux. La couverture des fournisseurs connectés varie. LIGHTNING nécessite un fournisseur connecté pris en charge. CELO (Celo), MODE (Mode) et PLUME (Plume) font l'objet d'un filtrage via un compte TRM Labs connecté ; le filtrage géré renvoie une réponse 400 pour ceux-ci. Alias : `currency`.",
                    "enum": [
                      "BTC",
                      "LIGHTNING",
                      "ETH",
                      "LTC",
                      "XRP",
                      "BCH",
                      "DOGE",
                      "TRX",
                      "SOL",
                      "MATIC",
                      "BNB",
                      "USDT",
                      "USDC",
                      "BASE",
                      "OP",
                      "ARB",
                      "AVAX",
                      "ADA",
                      "XLM",
                      "HBAR",
                      "CELO",
                      "MODE",
                      "PLUME"
                    ],
                    "example": "ETH"
                  },
                  "direction": {
                    "type": "string",
                    "description": "Facultatif. Indique si l'adresse est filtrée en tant que contrepartie entrante (dépôt) ou sortante (retrait). Accepte `inbound`, `outbound`, `deposit` ou `withdrawal`. Par défaut, un filtrage pré-transfert neutre est appliqué en cas d'omission. Cette valeur est transmise au fournisseur uniquement à titre de contexte ; elle ne modifie pas les valeurs retournées `risk_score`, `severity`, ni la ventilation `source_of_funds`/`destination_of_funds`, qui sont toujours retournées toutes les deux, quelle que soit la valeur de `direction`. Modifier ou omettre `direction` ne nécessite donc pas de refiltrer une adresse.",
                    "enum": [
                      "inbound",
                      "outbound",
                      "deposit",
                      "withdrawal"
                    ]
                  }
                }
              },
              "example": {
                "wallet_address": "0x94f1b9b64e2932f6a2db338f616844400cd58e8a",
                "blockchain": "ETH"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/wallet-screening/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"wallet_address\": \"0x94f1b9b64e2932f6a2db338f616844400cd58e8a\",\n    \"blockchain\": \"ETH\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.wallet_screening.screen(\n    wallet_address=\"0x94f1b9b64e2932f6a2db338f616844400cd58e8a\",\n    blockchain=\"ETH\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.walletScreening.screen({\n  wallet_address: \"0x94f1b9b64e2932f6a2db338f616844400cd58e8a\",\n  blockchain: \"ETH\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.WalletScreening.Screen(ctx, didit.WalletScreeningScreenParams{\n\tWalletAddress: \"0x94f1b9b64e2932f6a2db338f616844400cd58e8a\",\n\tBlockchain:    didit.Some(didit.WalletScreeningScreenParamsBlockchain(\"ETH\")),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.WalletScreeningScreenParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.walletScreening().screen(WalletScreeningScreenParams.builder()\n        .walletAddress(\"0x94f1b9b64e2932f6a2db338f616844400cd58e8a\")\n        .blockchain(WalletScreeningScreenParams.Blockchain.of(\"ETH\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->walletScreening->screen([\n    'wallet_address' => '0x94f1b9b64e2932f6a2db338f616844400cd58e8a',\n    'blockchain' => 'ETH',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.wallet_screening.screen(\n  wallet_address: \"0x94f1b9b64e2932f6a2db338f616844400cd58e8a\",\n  blockchain: \"ETH\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.WalletScreening.ScreenAsync(new WalletScreeningScreenParams\n{\n    WalletAddress = \"0x94f1b9b64e2932f6a2db338f616844400cd58e8a\",\n    Blockchain = new WalletScreeningScreenParamsBlockchain(\"ETH\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le résultat normalisé du filtrage des portefeuilles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletScreeningResult"
                },
                "example": {
                  "provider": "merklescience",
                  "screening_type": "WALLET_SCREENING",
                  "risk_score": 95,
                  "severity": "CRITICAL",
                  "status": "SCREENED",
                  "summary": "Merkle Science risk: Critical (5/5). SANCTIONS HIT. Dominant risk: sanctioned. Driven by: the address is attributed to Sanctions / OFAC (Example Sanctions)",
                  "wallet_address": "0x94f1b9b64e2932f6a2db338f616844400cd58e8a",
                  "transaction_hash": null,
                  "blockchain": "ETH",
                  "block_timestamp": null,
                  "total_value_usd": null,
                  "fee_usd": null,
                  "sender_rows": [],
                  "receiver_rows": [],
                  "transaction_flows": [],
                  "transaction_flows_status": null,
                  "transaction_flows_error": null,
                  "source_of_funds": [
                    {
                      "category": "sanctioned",
                      "percentage": 100.0,
                      "amount_usd": 9813695.0,
                      "entity_name": "Example Sanctions",
                      "entity_type": "Sanctions",
                      "entity_subtype": "OFAC",
                      "hops": null,
                      "description": "Sanctions / OFAC",
                      "is_direct": true,
                      "exposure_direction": "incoming",
                      "exposure_type": "direct",
                      "provider_entity_id": "118885",
                      "provider_entity_type_id": "30",
                      "provider_entity_subtype_id": "125",
                      "country": "",
                      "raw_amount": null,
                      "raw_currency": null
                    }
                  ],
                  "destination_of_funds": [
                    {
                      "category": "defi",
                      "percentage": 84.824453,
                      "amount_usd": 7783414.38,
                      "entity_name": "Example DeFi 7",
                      "entity_type": "DeFi",
                      "entity_subtype": "Bridges",
                      "hops": null,
                      "description": "DeFi / Bridges",
                      "is_direct": false,
                      "exposure_direction": "outgoing",
                      "exposure_type": "indirect",
                      "provider_entity_id": "118459",
                      "provider_entity_type_id": "33",
                      "provider_entity_subtype_id": "143",
                      "country": "",
                      "raw_amount": null,
                      "raw_currency": null
                    },
                    {
                      "category": "defi",
                      "percentage": 15.175547,
                      "amount_usd": 1392494.37,
                      "entity_name": "Example DeFi 2",
                      "entity_type": "DeFi",
                      "entity_subtype": "Yield Aggregator",
                      "hops": null,
                      "description": "DeFi / Yield Aggregator",
                      "is_direct": false,
                      "exposure_direction": "outgoing",
                      "exposure_type": "indirect",
                      "provider_entity_id": "90192",
                      "provider_entity_type_id": "33",
                      "provider_entity_subtype_id": "142",
                      "country": "",
                      "raw_amount": null,
                      "raw_currency": null
                    }
                  ],
                  "counterparty_connections": [
                    {
                      "entity_name": "Example Sanctions",
                      "entity_type": "Sanctions",
                      "entity_subtype": "OFAC",
                      "risk_level": "critical",
                      "categories": [
                        "sanctioned"
                      ],
                      "received_usd": null,
                      "sent_usd": null,
                      "received_hops": null,
                      "sent_hops": null,
                      "percentage": 0.0,
                      "is_direct": true,
                      "country": null,
                      "provider_entity_id": null
                    },
                    {
                      "entity_name": "Example Sanctions",
                      "entity_type": "Sanctions",
                      "entity_subtype": "OFAC",
                      "risk_level": "critical",
                      "categories": [
                        "sanctioned"
                      ],
                      "received_usd": null,
                      "sent_usd": null,
                      "received_hops": null,
                      "sent_hops": null,
                      "percentage": 0.0,
                      "is_direct": true,
                      "country": null,
                      "provider_entity_id": null
                    }
                  ],
                  "network_nodes": [],
                  "network_edges": [],
                  "sanctions_hit": true,
                  "pep_counterparty": null,
                  "dominant_risk_category": "sanctioned",
                  "risk_factors": [
                    {
                      "source": "attribution",
                      "category": "sanctioned",
                      "label": "Sanctions / OFAC",
                      "entity_name": "Example Sanctions",
                      "direction": "attribution",
                      "exposure_type": "attribution",
                      "amount_usd": null,
                      "percentage": 0.0,
                      "is_high_risk": true,
                      "description": "the address is attributed to Sanctions / OFAC (Example Sanctions)"
                    },
                    {
                      "source": "exposure",
                      "category": "sanctioned",
                      "label": "Sanctions / OFAC",
                      "entity_name": "Example Sanctions",
                      "direction": "incoming",
                      "exposure_type": "direct",
                      "amount_usd": 9813695.0,
                      "percentage": 51.679304,
                      "is_high_risk": true,
                      "description": "51.6793% direct incoming exposure to Sanctions / OFAC (Example Sanctions)"
                    },
                    {
                      "source": "exposure",
                      "category": "defi",
                      "label": "DeFi / Bridges",
                      "entity_name": "Example DeFi 7",
                      "direction": "outgoing",
                      "exposure_type": "indirect",
                      "amount_usd": 7783414.38,
                      "percentage": 40.987766,
                      "is_high_risk": false,
                      "description": "40.9878% indirect outgoing exposure to DeFi / Bridges (Example DeFi 7)"
                    },
                    {
                      "source": "exposure",
                      "category": "defi",
                      "label": "DeFi / Yield Aggregator",
                      "entity_name": "Example DeFi 2",
                      "direction": "outgoing",
                      "exposure_type": "indirect",
                      "amount_usd": 1392494.37,
                      "percentage": 7.33293,
                      "is_high_risk": false,
                      "description": "7.33293% indirect outgoing exposure to DeFi / Yield Aggregator (Example DeFi 2)"
                    }
                  ],
                  "raw_response": {
                    "...": "provider-specific details"
                  },
                  "report_signature": "<hmac-sha256 over the result, scoped to your application>"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — adresse de portefeuille mal formée, `wallet_address` manquant, `blockchain` non prise en charge, `blockchain` omise pour une adresse dont le format n'indique aucun réseau, ou LIGHTNING sans connexion BYOK Marketplace à Elliptic ou Chainalysis."
          },
          "401": {
            "description": "`x-api-key` manquant ou invalide."
          },
          "409": {
            "description": "Aucun fournisseur AML n'est configuré pour l'application, ou le fournisseur configuré ne prend pas encore en charge le filtrage des portefeuilles. Configurez d'abord la surveillance des transactions."
          },
          "422": {
            "description": "`blockchain` est omis pour une adresse en `0x`, que tous les réseaux EVM partagent. Rien n'est filtré ni facturé ; renvoyez la requête avec `blockchain` défini sur l'une des valeurs de `candidate_chains`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "blockchain": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "A 0x address is valid on every EVM chain. Send blockchain as one of: ETH, BNB, MATIC, BASE, ARB, OP, CELO, MODE, PLUME."
                      ]
                    },
                    "candidate_chains": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "ETH",
                        "BNB",
                        "MATIC",
                        "BASE",
                        "ARB",
                        "OP",
                        "CELO",
                        "MODE",
                        "PLUME"
                      ]
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Le fournisseur AML n'a pas pu effectuer le filtrage. Réessayez plus tard."
          }
        }
      }
    },
    "/v3/wallet-screening/pdf/": {
      "post": {
        "summary": "Générer le résultat d'un filtrage des portefeuilles au format PDF",
        "description": "Complément sans état de `POST /v3/wallet-screening/` : republiez le corps JSON exact renvoyé par ce endpoint — y compris la `report_signature` qu'il a ajoutée — et recevez en retour un PDF aux couleurs de Didit présentant le même résultat. Aucun fournisseur n'est appelé et rien n'est facturé ni conservé ; cela ne fait que générer à nouveau le rendu d'un résultat que Didit a déjà produit. La signature associe le PDF à un résultat non modifié : toute modification de `risk_score`, `severity`, `sanctions_hit` ou de tout autre champ signé avant la republication échoue avec une erreur `400`.",
        "operationId": "screenWalletPdf",
        "x-didit-sdk": {
          "resource": "wallet_screening",
          "method": "screen_pdf",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "L'objet JSON non modifié renvoyé par `POST /v3/wallet-screening/`, incluant `report_signature`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/WalletScreeningResult"
                  }
                ],
                "required": [
                  "report_signature"
                ],
                "description": "Même format que la réponse `POST /v3/wallet-screening/` — transmettez ce corps de réponse tel quel, y compris `report_signature`."
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "# $RESULT is the saved JSON body from POST /v3/wallet-screening/\ncurl -X POST 'https://verification.didit.me/v3/wallet-screening/pdf/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d \"$RESULT\" \\\n  -o wallet_screening_report.pdf"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.wallet_screening.screen_pdf(\n    provider=\"your-provider\",\n    screening_type=\"WALLET_SCREENING\",\n    risk_score=1,\n    severity=\"UNKNOWN\",\n    status=\"SCREENED\",\n    summary=\"your-summary\",\n    wallet_address=\"your-wallet-address\",\n    blockchain=\"your-blockchain\",\n    source_of_funds=[{}],\n    destination_of_funds=[{}],\n    counterparty_connections=[{}],\n    sanctions_hit=True,\n    dominant_risk_category=\"your-dominant-risk-category\",\n    report_signature=\"your-report-signature\",\n)\nwith open(\"download.pdf\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.walletScreening.screenPdf({\n  provider: \"your-provider\",\n  screening_type: \"WALLET_SCREENING\",\n  risk_score: 1,\n  severity: \"UNKNOWN\",\n  status: \"SCREENED\",\n  summary: \"your-summary\",\n  wallet_address: \"your-wallet-address\",\n  blockchain: \"your-blockchain\",\n  source_of_funds: [{}],\n  destination_of_funds: [{}],\n  counterparty_connections: [{}],\n  sanctions_hit: true,\n  dominant_risk_category: \"your-dominant-risk-category\",\n  report_signature: \"your-report-signature\",\n});\nawait writeFile(\"download.pdf\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.WalletScreening.ScreenPDF(ctx, didit.WalletScreeningResultParam{\n\tProvider:                \"your-provider\",\n\tScreeningType:           \"WALLET_SCREENING\",\n\tRiskScore:               1,\n\tSeverity:                \"UNKNOWN\",\n\tStatus:                  \"SCREENED\",\n\tSummary:                 \"your-summary\",\n\tWalletAddress:           \"your-wallet-address\",\n\tBlockchain:              \"your-blockchain\",\n\tSourceOfFunds:           []didit.WalletScreeningResultParamSourceOfFunds{{}},\n\tDestinationOfFunds:      []didit.WalletScreeningResultParamDestinationOfFunds{{}},\n\tCounterpartyConnections: []didit.WalletScreeningResultParamCounterpartyConnections{{}},\n\tSanctionsHit:            true,\n\tDominantRiskCategory:    didit.String(\"your-dominant-risk-category\"),\n\tReportSignature:         \"your-report-signature\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.WalletScreeningResult;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.walletScreening().screenPdf(WalletScreeningResult.builder()\n        .provider(\"your-provider\")\n        .screeningType(WalletScreeningResult.ScreeningType.of(\"WALLET_SCREENING\"))\n        .riskScore(1L)\n        .severity(WalletScreeningResult.Severity.of(\"UNKNOWN\"))\n        .status(WalletScreeningResult.Status.of(\"SCREENED\"))\n        .summary(\"your-summary\")\n        .walletAddress(\"your-wallet-address\")\n        .blockchain(\"your-blockchain\")\n        .sourceOfFunds(List.of(WalletScreeningResult.SourceOfFunds.builder()\n                .build()))\n        .destinationOfFunds(List.of(WalletScreeningResult.DestinationOfFunds.builder()\n                .build()))\n        .counterpartyConnections(List.of(WalletScreeningResult.CounterpartyConnections.builder()\n                .build()))\n        .sanctionsHit(true)\n        .dominantRiskCategory(\"your-dominant-risk-category\")\n        .reportSignature(\"your-report-signature\")\n        .build())\n        .writeTo(Path.of(\"download.pdf\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->walletScreening->screenPdf([\n    'provider' => 'your-provider',\n    'screening_type' => 'WALLET_SCREENING',\n    'risk_score' => 1,\n    'severity' => 'UNKNOWN',\n    'status' => 'SCREENED',\n    'summary' => 'your-summary',\n    'wallet_address' => 'your-wallet-address',\n    'blockchain' => 'your-blockchain',\n    'source_of_funds' => [[]],\n    'destination_of_funds' => [[]],\n    'counterparty_connections' => [[]],\n    'sanctions_hit' => true,\n    'dominant_risk_category' => 'your-dominant-risk-category',\n    'report_signature' => 'your-report-signature',\n]);\n$content->saveTo('download.pdf');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.wallet_screening.screen_pdf(\n  provider: \"your-provider\",\n  screening_type: \"WALLET_SCREENING\",\n  risk_score: 1,\n  severity: \"UNKNOWN\",\n  status: \"SCREENED\",\n  summary: \"your-summary\",\n  wallet_address: \"your-wallet-address\",\n  blockchain: \"your-blockchain\",\n  source_of_funds: [{}],\n  destination_of_funds: [{}],\n  counterparty_connections: [{}],\n  sanctions_hit: true,\n  dominant_risk_category: \"your-dominant-risk-category\",\n  report_signature: \"your-report-signature\"\n)\nFile.binwrite(\"download.pdf\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.WalletScreening.ScreenPdfAsync(new WalletScreeningResult\n{\n    Provider = \"your-provider\",\n    ScreeningType = \"WALLET_SCREENING\",\n    RiskScore = 1,\n    Severity = \"UNKNOWN\",\n    Status = \"SCREENED\",\n    Summary = \"your-summary\",\n    WalletAddress = \"your-wallet-address\",\n    Blockchain = \"your-blockchain\",\n    SourceOfFunds = new WalletScreeningResultSourceOfFunds[] { new() },\n    DestinationOfFunds = new WalletScreeningResultDestinationOfFunds[] { new() },\n    CounterpartyConnections = new WalletScreeningResultCounterpartyConnections[] { new() },\n    SanctionsHit = true,\n    DominantRiskCategory = \"your-dominant-risk-category\",\n    ReportSignature = \"your-report-signature\",\n});\nawait content.SaveToAsync(\"download.pdf\");"
          }
        ],
        "responses": {
          "200": {
            "description": "Le document PDF généré, renvoyé directement au format binaire `application/pdf` — il n'y a pas d'encapsulation JSON.",
            "headers": {
              "Content-Disposition": {
                "description": "`attachment; filename=wallet_screening_{address}.pdf`, dérivé de `wallet_address` (ou `transaction_hash`) dans le résultat republié.",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=wallet_screening_0x28c6c06298d514db0899.pdf"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Le corps n'est pas un objet JSON correspondant au format de résultat du filtrage des portefeuilles, ou `report_signature` est manquant ou ne correspond pas aux champs republiés (modifié ou tronqué avant la republication).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "examples": {
                  "Not an object": {
                    "value": {
                      "non_field_errors": [
                        "Expected a JSON object matching a wallet-screening result."
                      ]
                    }
                  },
                  "Missing or invalid signature": {
                    "value": {
                      "report_signature": [
                        "This wallet-screening result is missing or fails its report signature - repost the exact JSON returned by the wallet-screening endpoint, unmodified."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`x-api-key` manquant ou invalide."
          }
        }
      }
    },
    "/v3/transactions/": {
      "get": {
        "summary": "Lister les transactions",
        "description": "Liste paginée des transactions surveillées, de la plus récente à la plus ancienne (`txn_date` décroissant). `count` est plafonné à 100 ; utilisez `total_transactions` pour obtenir le nombre réel de lignes. Cet endpoint ne prend pas en charge les paramètres de filtrage ou de recherche.",
        "operationId": "listTransactions",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "description": "Taille de page. Vaut 50 par défaut si omis. Aucun maximum n'est imposé, mais conservez des pages de petite taille pour limiter la latence."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "description": "Décalage de départ (base zéro) du premier enregistrement à retourner. Privilégiez l'utilisation de l'URL `next` de la page précédente."
          },
          {
            "name": "travel_rule_status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Renvoie uniquement les transactions dont le transfert Travel Rule est exactement dans ce statut (par exemple `ON_HOLD` ou `AWAITING_COUNTERPARTY`). `count` applique ce filtre ; `total_transactions` compte toujours chaque transaction dans l'application."
          },
          {
            "name": "assignee",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Séparés par des virgules ; une transaction correspond lorsqu'elle remplit l'une des valeurs. `unassigned` correspond à ce qui n'est encore attribué à personne, `rules` correspond à ce que les règles ont décidé d'elles-mêmes sans réviseur, et l'e-mail d'un membre correspond au réviseur qui lui est assigné. `me` représente le réviseur connecté à la console, ainsi une clé API envoyant `me` reçoit un `400`."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/transactions/?limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.transactions.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.transactions.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Transactions.ListAutoPaging(ctx, didit.TransactionsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.transactions().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->transactions->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.transactions.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Transactions.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginée des résumés de transactions, de la plus récente à la plus ancienne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre plafonné de transactions correspondantes (exact jusqu'à 100, plafonné au-delà). Utilisez `total_transactions` pour obtenir le décompte réel lors de la pagination."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "total_transactions": {
                      "type": "integer",
                      "description": "Nombre total exact de transactions (non supprimées) pour l'application. Présent dans les réponses paginées."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Identifiant de transaction Didit stable. À utiliser comme `{transaction_id}` dans les appels de détails, de notes et connexes."
                          },
                          "transaction_number": {
                            "type": "integer",
                            "description": "Numéro de transaction séquentiel propre à l'application affiché dans la console (ex. `4123`)."
                          },
                          "txn_id": {
                            "type": "string",
                            "description": "Identifiant fourni par le client issu de l'appel de création (128 caractères max). Unique par application."
                          },
                          "transaction_type": {
                            "type": "string",
                            "description": "Catégorie de premier niveau telle que stockée : `finance`, `kyc`, `travelRule`, `userPlatformEvent`, `gamblingBet`, `gamblingLimitChange`, `gamblingBonusChange`, `auditTrailEvent`. Notez que les valeurs composées de plusieurs mots sont renvoyées en camelCase même lorsqu'elles ont été transmises en snake_case."
                          },
                          "action_type": {
                            "type": "string",
                            "description": "Sous-type au sein de la catégorie (par exemple `deposit`, `withdrawal`, `transfer`)."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "APPROVED",
                              "IN_REVIEW",
                              "DECLINED",
                              "AWAITING_USER"
                            ],
                            "description": "Verdict actuel de la surveillance."
                          },
                          "direction": {
                            "type": "string",
                            "enum": [
                              "INBOUND",
                              "OUTBOUND"
                            ],
                            "description": "Direction relative au sujet. Stockée en majuscules quelle que soit la casse fournie."
                          },
                          "amount": {
                            "type": "string",
                            "description": "Montant de la transaction sous forme de chaîne décimale sans les zéros de fin (par ex. `\"1500\"`, `\"0.5\"`, `\"0.123456789012345678\"`). Jusqu'à 18 décimales."
                          },
                          "currency": {
                            "type": "string",
                            "description": "Code devise de `amount`. Tout code alphabétique ISO 4217 est accepté (par ex. `EUR`, `USD`, `NGN`), ainsi qu'un symbole d'actif crypto (par ex. `BTC`). Privilégiez un code actuellement en circulation. Tous les codes acceptés ne disposent pas d'un taux de change : lorsqu'aucun taux n'est disponible pour le code (par exemple l'unité de compte ISO `XSU`, ou un symbole crypto dont Didit n'établit pas le prix), la conversion automatique échoue et `preferred_currency_amount` est retourné nul, sauf si la requête a fourni un montant pré-converti `amount_in_default_currency`."
                          },
                          "preferred_currency_amount": {
                            "type": "string",
                            "nullable": true,
                            "description": "`amount` converti dans la devise préférée de l'application, lorsqu'il est disponible."
                          },
                          "preferred_currency_code": {
                            "type": "string",
                            "nullable": true,
                            "description": "Code de devise préféré utilisé pour `preferred_currency_amount` - la devise de base de l'application, tout code ISO 4217 actuellement en circulation. Un code sans taux de change disponible laisse `preferred_currency_amount` à null, sauf si la requête a fourni un `amount_in_default_currency` pré-converti."
                          },
                          "payment_details": {
                            "type": "string",
                            "nullable": true,
                            "description": "Référence ou mémo de paiement en texte libre issu de la soumission."
                          },
                          "score": {
                            "type": "integer",
                            "description": "Score de risque (généralement 0–100). Plus il est élevé, plus le risque est grand."
                          },
                          "severity": {
                            "type": "string",
                            "nullable": true,
                            "enum": [
                              "UNKNOWN",
                              "LOW",
                              "MEDIUM",
                              "HIGH",
                              "CRITICAL"
                            ],
                            "description": "Gravité catégorielle du risque définie par les règles/fournisseurs (`UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`). `null` jusqu'à ce qu'un élément la définisse."
                          },
                          "subject_name": {
                            "type": "string",
                            "nullable": true,
                            "description": "Nom complet de la partie `APPLICANT`."
                          },
                          "subject_vendor_data": {
                            "type": "string",
                            "nullable": true,
                            "description": "Votre identifiant interne d'utilisateur/entreprise pour le candidat."
                          },
                          "subject_country": {
                            "type": "string",
                            "nullable": true,
                            "description": "Code pays du demandeur, issu de l'élément soumis `address.country` (généralement ISO 3166-1 alpha-3)."
                          },
                          "counterparty_name": {
                            "type": "string",
                            "nullable": true,
                            "description": "Nom complet de la partie `COUNTERPARTY`, le cas échéant."
                          },
                          "counterparty_vendor_data": {
                            "type": "string",
                            "nullable": true,
                            "description": "Votre identifiant interne pour la contrepartie."
                          },
                          "counterparty_country": {
                            "type": "string",
                            "nullable": true,
                            "description": "Code pays de la contrepartie, issu de l'élément soumis `address.country`."
                          },
                          "tags": {
                            "type": "array",
                            "description": "Tags associés à la transaction (manuellement ou par des règles).",
                            "items": {
                              "type": "object",
                              "properties": {
                                "uuid": {
                                  "type": "string",
                                  "format": "uuid"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "color": {
                                  "type": "string"
                                },
                                "description": {
                                  "type": "string",
                                  "nullable": true
                                },
                                "source": {
                                  "type": "string",
                                  "enum": [
                                    "didit",
                                    "custom"
                                  ],
                                  "description": "Indique si le tag est un préréglage Didit ou un tag personnalisé."
                                }
                              }
                            }
                          },
                          "txn_date": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Date et heure auxquelles la transaction a eu lieu (à partir de `transaction_at` lors de la création)."
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Date et heure auxquelles Didit a enregistré la soumission."
                          },
                          "decision_reason_code": {
                            "type": "string",
                            "nullable": true,
                            "description": "Raison lisible par machine pour le `status` actuel (par ex. `WALLET_HIGH_RISK`)."
                          },
                          "decision_reason_label": {
                            "type": "string",
                            "nullable": true,
                            "description": "Libellé lisible par l'humain pour `decision_reason_code`."
                          },
                          "assigned_to_name": {
                            "type": "string",
                            "nullable": true,
                            "description": "Nom d'affichage du réviseur de la Console assigné à cette transaction."
                          },
                          "travel_rule_status": {
                            "type": "string",
                            "nullable": true,
                            "description": "Statut du transfert Travel Rule de la transaction (par exemple `COMPLETED`), ou `null` lorsqu'il n'en a aucun."
                          },
                          "travel_rule": {
                            "nullable": true,
                            "allOf": [
                              {
                                "$ref": "#/components/schemas/TransactionTravelRule"
                              }
                            ],
                            "description": "Le transfert Travel Rule de la transaction, le même bloc que `travel_rule` sur `GET /v3/transactions/{transaction_id}/`, ou `null` lorsque la transaction n'en a aucun."
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Single transaction": {
                    "value": {
                      "count": 1,
                      "next": null,
                      "previous": null,
                      "total_transactions": 1,
                      "results": [
                        {
                          "uuid": "abcdef12-3456-4890-abcd-ef1234567890",
                          "transaction_number": 4123,
                          "txn_id": "your-txn-2026-05-17-001",
                          "transaction_type": "finance",
                          "action_type": "withdrawal",
                          "status": "IN_REVIEW",
                          "direction": "OUTBOUND",
                          "amount": "1500",
                          "currency": "EUR",
                          "preferred_currency_amount": "1620.45",
                          "preferred_currency_code": "USD",
                          "payment_details": "Withdrawal to crypto wallet",
                          "txn_date": "2026-05-17T08:42:00Z",
                          "created_at": "2026-05-17T08:42:11Z",
                          "score": 78,
                          "severity": "HIGH",
                          "decision_reason_code": "WALLET_HIGH_RISK",
                          "decision_reason_label": "Destination wallet flagged as high risk",
                          "tags": [
                            {
                              "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                              "name": "Manual review",
                              "color": "#F59E0B",
                              "description": null,
                              "source": "custom"
                            }
                          ],
                          "subject_name": "Maria Garcia",
                          "subject_vendor_data": "user-12345",
                          "counterparty_name": null,
                          "counterparty_vendor_data": null,
                          "counterparty_country": null,
                          "subject_country": null,
                          "assigned_to_name": "Alex Reviewer",
                          "travel_rule_status": null,
                          "travel_rule": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas lister les transactions pour cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer une transaction",
        "description": "Soumettez une transaction pour une surveillance synchrone AML/de risque. La transaction est créée avec le statut `APPROVED`, puis vos règles (et le filtrage crypto, le cas échéant) s'exécutent en ligne et peuvent faire passer le `status` renvoyé à `IN_REVIEW` ou `DECLINED`. **`transaction_id` est votre clé d'idempotence** (max. 128 caractères, unique par application) ; le réutiliser renvoie 400. Un webhook `transaction.created` est envoyé en cas de succès pour les applications en production. Les applications sandbox ne sont pas facturées et n'émettent pas de webhooks `transaction.created` ou `transaction.status.updated`. Les échanges Travel Rule en sandbox émettent des webhooks `travel_rule.status.updated` avec `environment: sandbox`. Un transfert Travel Rule est stocké et renvoyé avant que toute contrepartie ne soit contactée : `travel_rule.status` renvoie `AWAITING_COUNTERPARTY` (ou `NOT_APPLICABLE` en dessous de votre seuil, `UNCONFIRMED_OWNERSHIP` pour un portefeuille auto-hébergé déclaré, `COMPLETED` lorsque l'autre portefeuille est votre propre portefeuille vérifié) et `travel_rule.protocol` est nul. Didit choisit ensuite le canal et envoie l'échange, et chaque changement de statut ultérieur du transfert, y compris `COUNTERPARTY_VASP_NOT_FOUND` lorsqu'aucun canal n'atteint la contrepartie, arrive sous la forme d'un webhook `travel_rule.status.updated`. Vos règles s'exécutent à nouveau lorsque le canal ou le statut change.",
        "operationId": "createTransaction",
        "tags": [
          "Transactions"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/transactions/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"transaction_id\": \"your-txn-2026-05-17-001\",\n    \"transaction_category\": \"finance\",\n    \"transaction_details\": {\n      \"direction\": \"outbound\",\n      \"amount\": 1500,\n      \"currency\": \"EUR\",\n      \"action_type\": \"withdrawal\"\n    },\n    \"subject\": {\n      \"entity_type\": \"individual\",\n      \"vendor_data\": \"user-12345\",\n      \"full_name\": \"Maria Garcia\"\n    }\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.create(\n    transaction_id=\"your-txn-2026-05-17-001\",\n    transaction_category=\"finance\",\n    transaction_details={\n        \"direction\": \"outbound\",\n        \"amount\": 1500.0,\n        \"currency\": \"EUR\",\n        \"action_type\": \"withdrawal\",\n    },\n    subject={\n        \"entity_type\": \"individual\",\n        \"vendor_data\": \"user-12345\",\n        \"full_name\": \"Maria Garcia\",\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.create({\n  transaction_id: \"your-txn-2026-05-17-001\",\n  transaction_category: \"finance\",\n  transaction_details: {\n    direction: \"outbound\",\n    amount: 1500.0,\n    currency: \"EUR\",\n    action_type: \"withdrawal\",\n  },\n  subject: {\n    entity_type: \"individual\",\n    vendor_data: \"user-12345\",\n    full_name: \"Maria Garcia\",\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Create(ctx, didit.TransactionsCreateParams{\n\tTransactionID:       \"your-txn-2026-05-17-001\",\n\tTransactionCategory: \"finance\",\n\tTransactionDetails: didit.TransactionsCreateParamsTransactionDetails{\n\t\tDirection:  \"outbound\",\n\t\tAmount:     1500.0,\n\t\tCurrency:   \"EUR\",\n\t\tActionType: didit.String(\"withdrawal\"),\n\t},\n\tSubject: didit.TransactionsCreateParamsSubject{\n\t\tEntityType: didit.String(\"individual\"),\n\t\tVendorData: \"user-12345\",\n\t\tFullName:   \"Maria Garcia\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TransactionsCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().create(TransactionsCreateParams.builder()\n        .transactionId(\"your-txn-2026-05-17-001\")\n        .transactionCategory(TransactionsCreateParams.TransactionCategory.of(\"finance\"))\n        .transactionDetails(TransactionsCreateParams.TransactionDetails.builder()\n                .direction(TransactionsCreateParams.TransactionDetails.Direction.of(\"outbound\"))\n                .amount(1500.0)\n                .currency(\"EUR\")\n                .actionType(\"withdrawal\")\n                .build())\n        .subject(TransactionsCreateParams.Subject.builder()\n                .entityType(\"individual\")\n                .vendorData(\"user-12345\")\n                .fullName(\"Maria Garcia\")\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->create([\n    'transaction_id' => 'your-txn-2026-05-17-001',\n    'transaction_category' => 'finance',\n    'transaction_details' => [\n        'direction' => 'outbound',\n        'amount' => 1500.0,\n        'currency' => 'EUR',\n        'action_type' => 'withdrawal',\n    ],\n    'subject' => [\n        'entity_type' => 'individual',\n        'vendor_data' => 'user-12345',\n        'full_name' => 'Maria Garcia',\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.create(\n  transaction_id: \"your-txn-2026-05-17-001\",\n  transaction_category: \"finance\",\n  transaction_details: {\n    direction: \"outbound\",\n    amount: 1500.0,\n    currency: \"EUR\",\n    action_type: \"withdrawal\",\n  },\n  subject: {\n    entity_type: \"individual\",\n    vendor_data: \"user-12345\",\n    full_name: \"Maria Garcia\",\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.CreateAsync(new TransactionsCreateParams\n{\n    TransactionId = \"your-txn-2026-05-17-001\",\n    TransactionCategory = \"finance\",\n    TransactionDetails = new()\n    {\n        Direction = \"outbound\",\n        Amount = 1500.0,\n        Currency = \"EUR\",\n        ActionType = \"withdrawal\",\n    },\n    Subject = new()\n    {\n        EntityType = \"individual\",\n        VendorData = \"user-12345\",\n        FullName = \"Maria Garcia\",\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "transaction_id": {
                    "type": "string",
                    "description": "Votre identifiant unique pour cette transaction (128 caractères maximum).",
                    "example": "your-txn-2026-05-17-001"
                  },
                  "transaction_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Date et heure auxquelles la transaction a eu lieu. Prend par défaut l'heure actuelle si omis."
                  },
                  "time_zone": {
                    "type": "string",
                    "description": "Identifiant de fuseau horaire IANA, par exemple `Europe/Madrid`."
                  },
                  "transaction_category": {
                    "type": "string",
                    "description": "Catégorie de la transaction. Les alias en CamelCase (`travelRule`, `userPlatformEvent`, `gamblingBet`, …) sont également acceptés ; la valeur stockée/renvoyée est en camelCase pour les catégories composées de plusieurs mots.",
                    "example": "finance",
                    "enum": [
                      "finance",
                      "kyc",
                      "travel_rule",
                      "user_event",
                      "audit_trail_event",
                      "gambling_bet",
                      "gambling_limit_change",
                      "gambling_bonus_change",
                      "travelRule"
                    ]
                  },
                  "transaction_details": {
                    "type": "object",
                    "description": "Détails financiers principaux de la transaction.",
                    "required": [
                      "direction",
                      "amount",
                      "currency"
                    ],
                    "properties": {
                      "direction": {
                        "type": "string",
                        "description": "Direction de la transaction par rapport au sujet. Insensible à la casse ; `in`/`out` sont acceptés comme alias. Renvoyée en majuscules (`INBOUND`/`OUTBOUND`).",
                        "example": "outbound",
                        "enum": [
                          "inbound",
                          "outbound",
                          "in",
                          "out"
                        ]
                      },
                      "amount": {
                        "type": "number",
                        "description": "Montant de la transaction (jusqu'à 18 décimales). Envoyez-le sous forme de chaîne décimale (par ex. `\"0.123456789012345678\"`) lorsque la précision exacte importe : un nombre JSON est d'abord analysé comme un flottant binaire, donc les chiffres au-delà d'environ 15 chiffres significatifs sont arrondis avant que le montant ne soit stocké. Doit être supérieur ou égal à zéro : la direction porte le signe, et un montant négatif renvoie `400`.",
                        "example": 1500
                      },
                      "currency": {
                        "type": "string",
                        "description": "Code devise. Tout code alphabétique ISO 4217 est accepté (par ex. `EUR`, `USD`, `NGN`), ainsi qu'un symbole d'actif crypto (par ex. `BTC`). Privilégiez un code actuellement en circulation. Tous les codes acceptés ne disposent pas d'un taux de change : lorsqu'aucun taux n'est disponible pour le code (par exemple l'unité de compte ISO `XSU`, ou un symbole crypto dont Didit n'établit pas le prix), la conversion automatique échoue et `preferred_currency_amount` est retourné nul, sauf si la requête a fourni un montant pré-converti `amount_in_default_currency`.",
                        "example": "EUR"
                      },
                      "currency_kind": {
                        "type": "string",
                        "description": "Indique si la devise est `fiat` ou `crypto`."
                      },
                      "amount_in_default_currency": {
                        "type": "number",
                        "nullable": true,
                        "description": "Montant pré-converti dans la devise par défaut. S'il est omis, une conversion de change automatique est tentée. Doit être supérieur ou égal à zéro."
                      },
                      "default_currency": {
                        "type": "string",
                        "description": "Le code de devise par défaut pour le montant converti. Tout code ISO 4217 actuellement en circulation."
                      },
                      "payment_details": {
                        "type": "string",
                        "nullable": true,
                        "description": "Référence ou mémo de paiement en texte libre."
                      },
                      "payment_reference_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "Référence du système de paiement externe. Pour le filtrage AML par hachage de transaction crypto, envoyez le hachage de transaction blockchain et fournissez également `subject.payment_method.account_id` avec l'adresse associée."
                      },
                      "action_type": {
                        "type": "string",
                        "nullable": true,
                        "description": "Sous-type de la transaction, par exemple `deposit`, `withdrawal`, `transfer`."
                      },
                      "crypto_params": {
                        "type": "object",
                        "description": "Sélection du réseau crypto, distincte de la devise (le symbole de l'actif). L'enregistrement d'un symbole de token personnalisé ne garantit pas la couverture du hash de transaction pour son contrat.",
                        "properties": {
                          "crypto_chain": {
                            "type": "string",
                            "description": "Réseau effectif utilisé pour le filtrage. Le filtrage géré prend en charge BTC, ETH, LTC, XRP, BCH, DOGE, TRX, SOL, MATIC, BNB, BASE (Base), OP (Optimism), ARB (Arbitrum One), AVAX (Avalanche C-Chain), ADA (Cardano), XLM (Stellar) et HBAR (Hedera). Les noms usuels de réseau sont également acceptés, par exemple POLYGON ou POL pour MATIC, BSC pour BNB et TRON pour TRX. Spécifiez-le systématiquement pour les tokens multi-réseaux. En son absence pour USDT, USDC ou ETH transmis avec un hachage de transaction en 0x, Didit recherche le hachage sur Ethereum, BNB Chain, Polygon, Base, Arbitrum et Optimism, puis le filtre sur le réseau où il est trouvé ; si aucun réseau ne le contient, la transaction n'est pas filtrée et custom_values.aml_screening_status prend la valeur FAILED avec le motif dans custom_values.aml_screening_error. En son absence pour USDT ou USDC filtrés par portefeuille (sans hachage de transaction), une adresse Tron est filtrée sur Tron, une adresse Solana sur Solana, et une adresse en 0x sur le premier de ces six réseaux où elle a émis une transaction ou détient le token, ou sur Ethereum si elle n'est active sur aucun d'entre eux. La couverture des fournisseurs connectés varie ; LIGHTNING nécessite un fournisseur connecté compatible.",
                            "example": "BASE"
                          }
                        }
                      }
                    }
                  },
                  "subject": {
                    "type": "object",
                    "description": "L'objet (demandeur) de la transaction.",
                    "required": [
                      "vendor_data",
                      "full_name"
                    ],
                    "properties": {
                      "entity_type": {
                        "type": "string",
                        "description": "Type d'entité : `individual` ou `company`."
                      },
                      "vendor_data": {
                        "type": "string",
                        "description": "Votre identifiant interne d'utilisateur/entreprise.",
                        "example": "user-12345"
                      },
                      "full_name": {
                        "type": "string",
                        "description": "Nom complet du sujet.",
                        "example": "Maria Garcia"
                      },
                      "first_name": {
                        "type": "string",
                        "description": "Prénom du sujet."
                      },
                      "last_name": {
                        "type": "string",
                        "description": "Nom de famille de la personne concernée."
                      },
                      "date_of_birth": {
                        "type": "string",
                        "format": "date",
                        "description": "Date de naissance (YYYY-MM-DD)."
                      },
                      "address": {
                        "type": "object",
                        "description": "Objet d'adresse.",
                        "properties": {
                          "country": {
                            "type": "string",
                            "description": "Code pays (ISO 3166-1 alpha-3 recommandé). Copié dans le `country_code` de la partie."
                          },
                          "town": {
                            "type": "string"
                          },
                          "state": {
                            "type": "string"
                          },
                          "street": {
                            "type": "string"
                          },
                          "post_code": {
                            "type": "string"
                          }
                        }
                      },
                      "institution_details": {
                        "type": "object",
                        "description": "Informations sur l'établissement (pour les sujets institutionnels).",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "address": {
                            "type": "object"
                          }
                        }
                      },
                      "device_context": {
                        "type": "object",
                        "description": "Contexte de l'appareil capturé au moment de la transaction. browser_family et platform doivent être envoyés sous forme de clés de premier niveau explicites — ils ne sont pas dérivés de user_agent. L'alias camelCase device est également accepté dans la requête.",
                        "properties": {
                          "fingerprint": {
                            "type": "string",
                            "description": "Empreinte unique de l'appareil."
                          },
                          "persistent_device_id": {
                            "type": "string",
                            "description": "Identifiant stable de l'appareil entre les sessions (schéma d'empreinte v2)."
                          },
                          "user_agent": {
                            "type": "string",
                            "description": "Chaîne de l'agent utilisateur du navigateur ou de l'application. Alias en CamelCase : userAgent."
                          },
                          "browser_family": {
                            "type": "string",
                            "description": "Famille du navigateur (ex. Chrome, Firefox, Safari). Doit être envoyée explicitement — elle n'est pas déduite de user_agent. Alias en CamelCase : browserFamily."
                          },
                          "browser_version": {
                            "type": "string",
                            "description": "Chaîne de version du navigateur. Doit être envoyée explicitement. Alias en CamelCase : browserVersion."
                          },
                          "platform": {
                            "type": "string",
                            "description": "Identifiant de plateforme (web, ios, android, macos, windows, linux). Doit être envoyé explicitement — il n'est pas déduit de user_agent."
                          },
                          "os_family": {
                            "type": "string",
                            "description": "Famille de système d'exploitation (par exemple iOS, Android, Windows). Alias CamelCase : osFamily."
                          },
                          "os_version": {
                            "type": "string",
                            "description": "Chaîne de version du système d'exploitation. Alias CamelCase : osVersion."
                          },
                          "accept_language": {
                            "type": "string",
                            "description": "Valeur de l'en-tête Accept-Language. Alias CamelCase : acceptLang."
                          },
                          "session_id": {
                            "type": "string",
                            "description": "Identifiant de session de la session actuelle de l'utilisateur. Stocké dans les métadonnées. Alias CamelCase : sessionId."
                          },
                          "session_age_ms": {
                            "type": "number",
                            "description": "Âge de la session utilisateur en millisecondes au moment de la transaction. Alias CamelCase : sessionAgeMs."
                          },
                          "network_context": {
                            "type": "object",
                            "description": "Contexte réseau avec adresse IP et géolocalisation. Un bloc ipInfo de premier niveau est également intégré dans cet objet.",
                            "properties": {
                              "ip_address": {
                                "type": "string",
                                "description": "Adresse du client. Alias CamelCase : ip."
                              },
                              "ip_country_code": {
                                "type": "string",
                                "description": "Pays déterminé par géolocalisation de l'IP (ISO 3166-1 alpha-3). Alias CamelCase : countryCode3."
                              },
                              "latitude": {
                                "type": "number",
                                "description": "Latitude géographique de l'IP. Alias CamelCase : lat."
                              },
                              "longitude": {
                                "type": "number",
                                "description": "Longitude géographique de l'IP. Alias CamelCase : lon."
                              }
                            }
                          }
                        }
                      },
                      "payment_method": {
                        "type": "object",
                        "description": "Moyen de paiement utilisé par le sujet.",
                        "properties": {
                          "method_type": {
                            "type": "string",
                            "description": "Type de moyen de paiement : `bank_card`, `bank_account`, `crypto_wallet`, `ewallet`, `unhosted_wallet`, `other`."
                          },
                          "account_id": {
                            "type": "string",
                            "description": "Identifiant de compte (par exemple IBAN, adresse de portefeuille). Pour le filtrage crypto, ce champ doit contenir l'adresse de portefeuille de ce participant. Le filtrage entrant des hachages de transaction nécessite l'adresse de dépôt du service/client sur le sujet. Le filtrage sortant utilise le portefeuille de destination sur la contrepartie. Pour un transfert crypto sur bitcoin ou Lightning, il peut s'agir d'une demande de paiement Lightning (facture BOLT11, offre BOLT12, LNURL) ou d'une Lightning Address : Didit stocke le bénéficiaire qu'elle désigne en tant que compte (\"\" lorsqu'aucun n'est désigné) et le contenu de la demande dans `chain_details.lightning` du transfert Travel Rule. Au maximum 255 caractères une fois stocké. Pour un transfert crypto sur bitcoin ou Lightning, il peut s'agir d'une demande de paiement Lightning (facture BOLT11, offre BOLT12, LNURL) ou d'une Lightning Address : Didit stocke le bénéficiaire qu'elle désigne en tant que compte (\"\" lorsqu'aucun n'est désigné) et le contenu de la demande dans `chain_details.lightning` du transfert Travel Rule. Au maximum 255 caractères une fois stocké."
                          },
                          "memo": {
                            "type": "string",
                            "maxLength": 256,
                            "description": "Le tag de destination ou le mémo qui fait partie du portefeuille sur un réseau à mémo (XRP, XLM, EOS, ATOM, HBAR). Sur une adresse d'échange partagée, chaque mémo constitue sa propre méthode de paiement. XRP : un tag de destination, un nombre entier de 0 à 4294967295 (un nombre JSON est accepté). XLM : un mémo texte jusqu'à 28 octets, un identifiant 64 bits ou un hachage de 32 octets en hexadécimal. EOS : jusqu'à 256 octets. ATOM : jusqu'à 256 caractères. HBAR : jusqu'à 100 octets. Les portefeuilles Bitcoin, EVM, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin et Lightning n'acceptent pas de mémo : en renseigner un renvoie une erreur `400`. Alias : `destinationTag` ou `destination_tag`."
                          },
                          "issuing_country": {
                            "type": "string",
                            "description": "Code pays ISO 3166-1 alpha-3 de l'émetteur."
                          }
                        }
                      }
                    }
                  },
                  "counterparty": {
                    "type": "object",
                    "description": "La contrepartie de la transaction (facultatif).",
                    "properties": {
                      "entity_type": {
                        "type": "string",
                        "description": "Type d'entité : `individual` ou `company`."
                      },
                      "vendor_data": {
                        "type": "string",
                        "description": "Votre identifiant interne pour la contrepartie."
                      },
                      "full_name": {
                        "type": "string",
                        "description": "Nom complet de la contrepartie."
                      },
                      "first_name": {
                        "type": "string"
                      },
                      "last_name": {
                        "type": "string"
                      },
                      "date_of_birth": {
                        "type": "string",
                        "format": "date"
                      },
                      "address": {
                        "type": "object",
                        "description": "Objet d'adresse avec `country` (ISO 3166-1 alpha-3)."
                      },
                      "institution_details": {
                        "type": "object"
                      },
                      "device_context": {
                        "type": "object",
                        "description": "Contexte de l'appareil pour la contrepartie. browser_family et platform doivent être envoyés sous forme de clés de premier niveau explicites — ils ne sont pas dérivés de user_agent.",
                        "properties": {
                          "fingerprint": {
                            "type": "string",
                            "description": "Empreinte unique de l'appareil."
                          },
                          "persistent_device_id": {
                            "type": "string",
                            "description": "Identifiant stable de l'appareil entre les sessions (schéma d'empreinte v2)."
                          },
                          "user_agent": {
                            "type": "string",
                            "description": "Chaîne de l'agent utilisateur du navigateur ou de l'application. Alias en CamelCase : userAgent."
                          },
                          "browser_family": {
                            "type": "string",
                            "description": "Famille du navigateur (ex. Chrome, Firefox, Safari). Doit être envoyée explicitement — elle n'est pas déduite de user_agent. Alias en CamelCase : browserFamily."
                          },
                          "browser_version": {
                            "type": "string",
                            "description": "Chaîne de version du navigateur. Doit être envoyée explicitement. Alias en CamelCase : browserVersion."
                          },
                          "platform": {
                            "type": "string",
                            "description": "Identifiant de plateforme (web, ios, android, macos, windows, linux). Doit être envoyé explicitement — il n'est pas déduit de user_agent."
                          },
                          "os_family": {
                            "type": "string",
                            "description": "Famille de système d'exploitation (par exemple iOS, Android, Windows). Alias CamelCase : osFamily."
                          },
                          "os_version": {
                            "type": "string",
                            "description": "Chaîne de version du système d'exploitation. Alias CamelCase : osVersion."
                          },
                          "accept_language": {
                            "type": "string",
                            "description": "Valeur de l'en-tête Accept-Language. Alias CamelCase : acceptLang."
                          },
                          "session_id": {
                            "type": "string",
                            "description": "Identifiant de session pour la session de la contrepartie. Stocké dans les métadonnées. Alias CamelCase : sessionId."
                          },
                          "session_age_ms": {
                            "type": "number",
                            "description": "Âge de la session utilisateur en millisecondes au moment de la transaction. Alias CamelCase : sessionAgeMs."
                          },
                          "network_context": {
                            "type": "object",
                            "description": "Contexte réseau avec adresse IP et géolocalisation. Un bloc ipInfo de premier niveau est également intégré dans cet objet.",
                            "properties": {
                              "ip_address": {
                                "type": "string",
                                "description": "Adresse du client. Alias CamelCase : ip."
                              },
                              "ip_country_code": {
                                "type": "string",
                                "description": "Pays déterminé par géolocalisation de l'IP (ISO 3166-1 alpha-3). Alias CamelCase : countryCode3."
                              },
                              "latitude": {
                                "type": "number",
                                "description": "Latitude géographique de l'IP. Alias CamelCase : lat."
                              },
                              "longitude": {
                                "type": "number",
                                "description": "Longitude géographique de l'IP. Alias CamelCase : lon."
                              }
                            }
                          }
                        }
                      },
                      "payment_method": {
                        "type": "object",
                        "description": "Moyen de paiement utilisé par la contrepartie. Sur les transactions travelRule, `method_type: \"unhosted_wallet\"` déclare le portefeuille de la contrepartie comme auto-hébergé : le transfert ignore le routage VASP-contrepartie, est créé directement sous `UNCONFIRMED_OWNERSHIP`, et (lorsque `auto_wallet_verification` est activé) une session de widget de propriété de portefeuille est générée automatiquement et renvoyée dans le bloc `action_required` de la transaction.",
                        "properties": {
                          "method_type": {
                            "type": "string",
                            "description": "Type de moyen de paiement : `bank_card`, `bank_account`, `crypto_wallet`, `ewallet`, `unhosted_wallet`, `other`. Utilisez `unhosted_wallet` pour déclarer un portefeuille auto-hébergé pour la Travel Rule."
                          },
                          "account_id": {
                            "type": "string",
                            "description": "Identifiant de compte (par exemple IBAN ou adresse de portefeuille). Pour un transfert crypto sur bitcoin ou Lightning, il peut s'agir d'une demande de paiement Lightning (facture BOLT11, offre BOLT12, LNURL) ou d'une Lightning Address : Didit stocke le bénéficiaire qu'elle désigne en tant que compte (\"\" lorsqu'aucun n'est désigné) et le contenu de la demande dans `chain_details.lightning` du transfert Travel Rule. Au maximum 255 caractères une fois stocké. Pour un transfert crypto sur bitcoin ou Lightning, il peut s'agir d'une demande de paiement Lightning (facture BOLT11, offre BOLT12, LNURL) ou d'une Lightning Address : Didit stocke le bénéficiaire qu'elle désigne en tant que compte (\"\" lorsqu'aucun n'est désigné) et le contenu de la demande dans `chain_details.lightning` du transfert Travel Rule. Au maximum 255 caractères une fois stocké."
                          },
                          "memo": {
                            "type": "string",
                            "maxLength": 256,
                            "description": "Le tag de destination ou le mémo qui fait partie du portefeuille sur un réseau à mémo (XRP, XLM, EOS, ATOM, HBAR). Sur une adresse d'échange partagée, chaque mémo constitue sa propre méthode de paiement. XRP : un tag de destination, un nombre entier de 0 à 4294967295 (un nombre JSON est accepté). XLM : un mémo texte jusqu'à 28 octets, un identifiant 64 bits ou un hachage de 32 octets en hexadécimal. EOS : jusqu'à 256 octets. ATOM : jusqu'à 256 caractères. HBAR : jusqu'à 100 octets. Les portefeuilles Bitcoin, EVM, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin et Lightning n'acceptent pas de mémo : en renseigner un renvoie une erreur `400`. Alias : `destinationTag` ou `destination_tag`."
                          },
                          "issuing_country": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  },
                  "custom_properties": {
                    "type": "object",
                    "description": "Paires clé-valeur arbitraires associées à la transaction. Chaque clé peut être référencée dans les conditions de règles avec le chemin de champ `custom_values.<key>`.",
                    "additionalProperties": true,
                    "example": {
                      "merchant_id": "test",
                      "bank_name": "test_2"
                    }
                  },
                  "travel_rule_details": {
                    "type": "object",
                    "description": "Données Travel Rule. Lorsque la Travel Rule est activée et que transaction_category est travel_rule, Didit gère l'échange lui-même : il ignore status, protocol, required ainsi que obligations_count, et utilise originator_data, beneficiary_data et metadata. Sinon, Didit stocke ces valeurs en tant qu'enregistrement Travel Rule passif. Tant que la Travel Rule est activée, un transfert sortant supérieur ou égal à votre seuil doit comporter les informations requises par son régime (TFR de l'UE ou Recommandation 16 du GAFI), vérifiées sur les volets que vous transmettez : un champ manquant renvoie une erreur 400 sous `travel_rule_details.originator_data` ou `travel_rule_details.beneficiary_data`, par exemple « Le TFR de l'UE exige le nom du donneur d'ordre. »",
                    "required": [
                      "status"
                    ],
                    "properties": {
                      "status": {
                        "type": "string",
                        "description": "Requis dès que vous envoyez travel_rule_details. L'un des statuts de transfert Travel Rule (par exemple AWAITING_COUNTERPARTY, COMPLETED, NOT_APPLICABLE) ; les graphies en minuscules et camelCase ainsi que les valeurs héritées UNKNOWN, COMPLIANT, PENDING_ACTION, PENDING_COUNTERPARTY, FAILED et EXEMPT sont également acceptées et mises en correspondance. Toute autre valeur renvoie 400."
                      },
                      "protocol": {
                        "type": "string"
                      },
                      "required": {
                        "type": "boolean"
                      },
                      "obligations_count": {
                        "type": "integer"
                      },
                      "originator_data": {
                        "type": "object",
                        "description": "Partie donneuse d'ordre, sous forme de champs plats ou d'une personne IVMS 101. Pour votre utilisateur disposant d'une vérification KYC approuvée, Didit remplace les champs contenus dans la vérification par les valeurs vérifiées (voir `metadata.originator_provenance`). Il doit s'agir d'un objet : toute autre valeur renvoie une erreur `400`. Sur un réseau à memo, une clé `memo` indique le memo ou le tag du portefeuille du donneur d'ordre."
                      },
                      "beneficiary_data": {
                        "type": "object",
                        "description": "Partie bénéficiaire, sous forme de champs plats ou d'une personne IVMS 101. Il doit s'agir d'un objet : tout autre type entraîne une erreur `400`. Pour acheminer le transfert, Didit lit `wallet_address` (une valeur vide est complétée à partir de `counterparty.payment_method.account_id`), `chain` (complété à partir de `transaction_details.crypto_params.crypto_chain` ou de `currency` lorsque celle-ci désigne une blockchain prise en charge), `name` (en se rabattant sur `counterparty.full_name`), `travel_address`, `counterparty_vasp_name`, `counterparty_vasp_lei` et `counterparty_vasp_email`. Sur un réseau à mémo, `memo` désigne le mémo ou le tag du portefeuille bénéficiaire ; `wallet_address` et `memo` l'emportent sur le moyen de paiement de la contrepartie."
                      },
                      "metadata": {
                        "type": "object"
                      },
                      "utxo": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/TravelRuleUtxo"
                          }
                        ],
                        "description": "Optionnel, blockchains UTXO uniquement (BTC, LTC, BCH, DOGE). Les entrées et sorties de la transaction, à partir desquelles Didit déduit le portefeuille du donneur d'ordre et la sortie du bénéficiaire lorsque vous ne les déclarez pas."
                      },
                      "originator": {
                        "type": "object",
                        "description": "Un bloc de donneur d'ordre IVMS 101 : `originatorPersons` (une `naturalPerson` ou `legalPerson` ; une personne morale fait de la partie une entreprise) et `accountNumber` (adresses de portefeuille). Utilisé pour `originator_data` lorsque cet objet est vide. Un bloc malformé renvoie 400 indexé par son chemin, par exemple `originator.originatorPersons`."
                      },
                      "beneficiary": {
                        "type": "object",
                        "description": "Un bloc de bénéficiaire IVMS 101 : `beneficiaryPersons` (une `naturalPerson` ou `legalPerson` ; une personne morale fait de la partie une entreprise) et `accountNumber` (adresses de portefeuille). Utilisé pour `beneficiary_data` lorsque cet objet est vide. Un bloc malformé renvoie 400 indexé par son chemin, par exemple `beneficiary.beneficiaryPersons`."
                      },
                      "ivms101": {
                        "type": "object",
                        "description": "Les blocs `originator` et `beneficiary` encapsulés dans un seul objet IVMS 101 (`IVMS101` est également accepté). Les blocs de premier niveau prévalent sur ceux du conteneur."
                      }
                    }
                  },
                  "network_snapshot": {
                    "type": "object",
                    "description": "Instantané précalculé du graphe de réseau.",
                    "properties": {
                      "nodes": {
                        "type": "array",
                        "items": {
                          "type": "object"
                        }
                      },
                      "edges": {
                        "type": "array",
                        "items": {
                          "type": "object"
                        }
                      },
                      "metrics": {
                        "type": "object"
                      }
                    }
                  },
                  "include_crypto_screening": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Remplacement par transaction pour le filtrage par analyse de la blockchain crypto. Lorsqu'il vaut `true`, le filtrage crypto est effectué quelle que soit la valeur par défaut de l'application. Lorsqu'il vaut `false`, le filtrage crypto est ignoré même s'il est activé dans les paramètres de l'application. Lorsqu'il est omis ou défini sur `null`, la valeur par défaut au niveau de l'application configurée dans la Console est utilisée. Le filtrage crypto nécessite `transaction_details.direction`, `currency_kind: \"crypto\"`, une chaîne ou une devise, ainsi que l'adresse de portefeuille sélectionnée par le sens de la transaction : le filtrage entrant pré-transfert utilise `counterparty.payment_method.account_id`, le filtrage entrant par hash de transaction utilise `subject.payment_method.account_id`, et le filtrage sortant utilise `counterparty.payment_method.account_id`. Lorsque `transaction_details.payment_reference_id` contient un hash de transaction de blockchain, Didit effectue le filtrage de la transaction et renvoie l'enrichissement du résumé de la transaction lorsqu'il est disponible."
                  }
                },
                "required": [
                  "transaction_id",
                  "transaction_category",
                  "transaction_details",
                  "subject"
                ]
              },
              "examples": {
                "Minimal fiat withdrawal": {
                  "summary": "Payload minimal acceptable pour un virement sortant en monnaie fiduciaire",
                  "value": {
                    "transaction_id": "your-txn-2026-05-17-001",
                    "transaction_category": "finance",
                    "transaction_details": {
                      "direction": "outbound",
                      "amount": 1500,
                      "currency": "EUR",
                      "action_type": "withdrawal"
                    },
                    "subject": {
                      "entity_type": "individual",
                      "vendor_data": "user-12345",
                      "full_name": "Maria Garcia"
                    }
                  }
                },
                "Crypto outbound with screening": {
                  "summary": "Retrait de crypto sortant vers un portefeuille auto-hébergé, filtrage optionnel",
                  "value": {
                    "transaction_id": "your-txn-2026-05-17-002",
                    "transaction_category": "finance",
                    "include_crypto_screening": true,
                    "transaction_details": {
                      "direction": "outbound",
                      "amount": 0.5,
                      "currency": "BTC",
                      "currency_kind": "crypto",
                      "amount_in_default_currency": 32500,
                      "default_currency": "USD",
                      "action_type": "withdrawal"
                    },
                    "subject": {
                      "entity_type": "individual",
                      "vendor_data": "user-12345",
                      "full_name": "Maria Garcia",
                      "payment_method": {
                        "method_type": "crypto_wallet",
                        "account_id": "bc1qexampleexchangewalletaddressxyz",
                        "issuing_country": "ESP"
                      }
                    },
                    "counterparty": {
                      "entity_type": "individual",
                      "payment_method": {
                        "method_type": "unhosted_wallet",
                        "account_id": "bc1qexampleexternalwalletaddressabc"
                      }
                    }
                  }
                },
                "Travel Rule transfer": {
                  "summary": "Transfert de crypto sortant avec données Travel Rule du donneur d'ordre/bénéficiaire",
                  "value": {
                    "transaction_id": "your-txn-2026-05-17-003",
                    "transaction_category": "travel_rule",
                    "transaction_details": {
                      "direction": "outbound",
                      "amount": 25000,
                      "currency": "USDT",
                      "currency_kind": "crypto",
                      "action_type": "transfer"
                    },
                    "subject": {
                      "entity_type": "individual",
                      "vendor_data": "user-12345",
                      "full_name": "Maria Garcia",
                      "date_of_birth": "1992-03-14",
                      "address": {
                        "country": "ESP",
                        "town": "Madrid",
                        "street": "Calle Mayor 1",
                        "post_code": "28013"
                      }
                    },
                    "counterparty": {
                      "entity_type": "individual",
                      "full_name": "John Beneficiary",
                      "institution_details": {
                        "name": "Beneficiary VASP, Inc.",
                        "code": "BVASP-US"
                      }
                    },
                    "travel_rule_details": {
                      "status": "AWAITING_COUNTERPARTY",
                      "protocol": "IVMS101",
                      "required": true,
                      "originator_data": {
                        "name": "Maria Garcia"
                      },
                      "beneficiary_data": {
                        "name": "John Beneficiary"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Transaction soumise et surveillée. Le corps contient l'ensemble des détails de la transaction (même structure que `GET /v3/transactions/{transaction_id}/`), reflétant les résultats des règles déjà appliquées.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionDetail"
                },
                "examples": {
                  "Approved with no rule hits": {
                    "value": {
                      "uuid": "abcdef12-3456-4890-abcd-ef1234567890",
                      "environment": "live",
                      "transaction_number": 4123,
                      "txn_id": "your-txn-2026-05-17-001",
                      "txn_date": "2026-05-17T08:42:00Z",
                      "zone_id": "Europe/Madrid",
                      "transaction_type": "finance",
                      "action_type": "withdrawal",
                      "direction": "OUTBOUND",
                      "status": "APPROVED",
                      "source": "LIVE",
                      "amount": "1500",
                      "currency": "EUR",
                      "currency_type": "fiat",
                      "amount_in_default_currency": "1620.45",
                      "default_currency_code": "USD",
                      "preferred_currency_amount": "1620.45",
                      "preferred_currency_code": "USD",
                      "payment_details": "Withdrawal to crypto wallet",
                      "payment_txn_id": null,
                      "score": 0,
                      "severity": null,
                      "decision_reason_code": null,
                      "decision_reason_label": null,
                      "vendor_data": "user-12345",
                      "metadata": {
                        "subject": {
                          "entity_type": "individual",
                          "vendor_data": "user-12345",
                          "full_name": "Maria Garcia",
                          "address": {},
                          "institution_details": {},
                          "device_context": {}
                        },
                        "counterparty": {}
                      },
                      "props": {},
                      "tags": [],
                      "parties": [
                        {
                          "uuid": "b1111111-2222-4333-8444-555555555555",
                          "role": "APPLICANT",
                          "entity_type": "individual",
                          "kind": "USER",
                          "vendor_data": "user-12345",
                          "full_name": "Maria Garcia",
                          "first_name": null,
                          "last_name": null,
                          "country_code": null,
                          "dob": null,
                          "address": {},
                          "institution_info": {},
                          "device": {},
                          "external_party_snapshot": null
                        }
                      ],
                      "payment_methods": [],
                      "documents": [],
                      "activities": [
                        {
                          "uuid": "d4e5f6a7-8901-4bcd-9ef0-123456789abc",
                          "activity_type": "TRANSACTION_CREATED",
                          "source": "TRANSACTION",
                          "status": "APPROVED",
                          "title": "withdrawal",
                          "description": "Transaction recorded.",
                          "metadata": {},
                          "occurred_at": "2026-05-17T08:42:11Z"
                        }
                      ],
                      "alerts": [],
                      "rule_runs": [],
                      "provider_results": [],
                      "travel_rule": null,
                      "network_snapshot": null,
                      "remediation": null,
                      "action_required": null,
                      "cost_breakdown": null
                    }
                  },
                  "Flagged for review": {
                    "value": {
                      "uuid": "abcdef12-3456-4890-abcd-ef1234567891",
                      "environment": "live",
                      "transaction_number": 4124,
                      "txn_id": "your-txn-2026-05-17-002",
                      "txn_date": "2026-05-17T08:42:00Z",
                      "zone_id": "Europe/Madrid",
                      "transaction_type": "finance",
                      "action_type": "withdrawal",
                      "direction": "OUTBOUND",
                      "status": "IN_REVIEW",
                      "source": "LIVE",
                      "amount": "0.5",
                      "currency": "BTC",
                      "currency_type": "crypto",
                      "amount_in_default_currency": "32500",
                      "default_currency_code": "USD",
                      "preferred_currency_amount": "32500",
                      "preferred_currency_code": "USD",
                      "payment_details": "Withdrawal to crypto wallet",
                      "payment_txn_id": null,
                      "score": 78,
                      "severity": "HIGH",
                      "decision_reason_code": "WALLET_HIGH_RISK",
                      "decision_reason_label": "Destination wallet flagged as high risk",
                      "vendor_data": "user-12345",
                      "metadata": {
                        "subject": {
                          "entity_type": "individual",
                          "vendor_data": "user-12345",
                          "full_name": "Maria Garcia",
                          "address": {},
                          "institution_details": {},
                          "device_context": {}
                        },
                        "counterparty": {}
                      },
                      "props": {
                        "order_id": "ord-9988"
                      },
                      "tags": [],
                      "parties": [
                        {
                          "uuid": "b1111111-2222-4333-8444-555555555555",
                          "role": "APPLICANT",
                          "entity_type": "individual",
                          "kind": "USER",
                          "vendor_data": "user-12345",
                          "full_name": "Maria Garcia",
                          "first_name": null,
                          "last_name": null,
                          "country_code": null,
                          "dob": null,
                          "address": {},
                          "institution_info": {},
                          "device": {},
                          "external_party_snapshot": null
                        }
                      ],
                      "payment_methods": [],
                      "documents": [],
                      "activities": [],
                      "alerts": [
                        {
                          "uuid": "a7b8c9d0-1234-4abc-9def-567890abcdef",
                          "title": "Destination wallet flagged as high risk",
                          "description": "Provider risk score exceeded the configured threshold.",
                          "severity": "HIGH",
                          "status": "OPEN",
                          "source": "RULE",
                          "metadata": {},
                          "created_at": "2026-05-17T08:42:12Z",
                          "due_at": null
                        }
                      ],
                      "rule_runs": [
                        {
                          "uuid": "e5f6a7b8-9012-4cde-af01-23456789abcd",
                          "rule": "f6a7b8c9-0123-4def-b012-3456789abcde",
                          "rule_title": "High-risk wallet screening",
                          "rule_description": null,
                          "rule_category": "crypto",
                          "matched": true,
                          "is_test": false,
                          "mode": "ACTIVE",
                          "severity": "HIGH",
                          "score_delta": 78,
                          "status_target": "IN_REVIEW",
                          "action_summary": "score +78; change_status:IN_REVIEW",
                          "metadata": {},
                          "created_at": "2026-05-17T08:42:12Z"
                        }
                      ],
                      "provider_results": [],
                      "travel_rule": null,
                      "network_snapshot": null,
                      "remediation": null,
                      "action_required": null,
                      "cost_breakdown": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Échec de validation (champs obligatoires manquants, `transaction_id` en doublon, valeur d'énumération inconnue, devise non valide, etc.).",
            "content": {
              "application/json": {
                "examples": {
                  "Missing required field": {
                    "value": {
                      "transaction_details": {
                        "amount": [
                          "This field is required."
                        ]
                      }
                    }
                  },
                  "Duplicate transaction_id": {
                    "value": {
                      "transaction_id": [
                        "A transaction with this transaction_id already exists."
                      ]
                    }
                  },
                  "Invalid category": {
                    "value": {
                      "non_field_errors": [
                        "Unsupported transaction category."
                      ]
                    }
                  },
                  "Missing subject identity": {
                    "value": {
                      "subject": [
                        "subject.vendor_data and subject.full_name are required."
                      ]
                    }
                  },
                  "Blocklisted participant": {
                    "value": {
                      "vendor_data": [
                        "The individual 'user-12345' is in the blocklist and cannot participate in transactions."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas soumettre de transactions pour cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Une autre requête avec le même `transaction_id` a créé la transaction pendant le traitement de celle-ci, de sorte qu'une seule des deux soumissions simultanées réussit. Lisez la transaction existante au lieu de la soumettre à nouveau.",
            "content": {
              "application/json": {
                "examples": {
                  "Concurrent duplicate": {
                    "value": {
                      "detail": "A transaction with this transaction_id already exists."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les créations de transactions et l'ingestion d'événements (`POST /v3/transactions/`, `POST /v3/events/`, `POST /v3/events/batch/`) partagent un quota de 600 requêtes par minute par clé API, distinct des 300 requêtes partagées par toutes les autres requêtes d'écriture. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer, arrondies à l'unité supérieure pour que la tentative se fasse dans la fenêtre suivante.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Ingestion rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "create",
          "auth": "api_key",
          "server": true
        }
      }
    },
    "/v3/transactions/{transaction_id}/": {
      "get": {
        "summary": "Obtenir la transaction",
        "description": "Récupérer l'enregistrement complet de surveillance pour une transaction : parties, score/gravité, exécutions de règles, alertes, résultat de la Travel Rule, session de remédiation.",
        "operationId": "getTransaction",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID de transaction stable attribué par Didit (le `uuid` renvoyé lors de la création / du listage, **et non** votre `txn_id`).",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "abcdef12-3456-7890-abcd-ef1234567890"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/transactions/abcdef12-3456-7890-abcd-ef1234567890/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.retrieve(\n    \"abcdef12-3456-7890-abcd-ef1234567890\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.retrieve(\"abcdef12-3456-7890-abcd-ef1234567890\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Retrieve(ctx, \"abcdef12-3456-7890-abcd-ef1234567890\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().retrieve(\"abcdef12-3456-7890-abcd-ef1234567890\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->retrieve('abcdef12-3456-7890-abcd-ef1234567890');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.retrieve(\"abcdef12-3456-7890-abcd-ef1234567890\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.RetrieveAsync(\"abcdef12-3456-7890-abcd-ef1234567890\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détails complets de la transaction.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionDetail"
                },
                "examples": {
                  "In review with an alert": {
                    "value": {
                      "uuid": "abcdef12-3456-4890-abcd-ef1234567890",
                      "environment": "live",
                      "transaction_number": 4123,
                      "txn_id": "your-txn-2026-05-17-001",
                      "txn_date": "2026-05-17T08:42:00Z",
                      "zone_id": "Europe/Madrid",
                      "transaction_type": "finance",
                      "action_type": "withdrawal",
                      "direction": "OUTBOUND",
                      "status": "IN_REVIEW",
                      "source": "LIVE",
                      "amount": "1500",
                      "currency": "EUR",
                      "currency_type": "fiat",
                      "amount_in_default_currency": "1620.45",
                      "default_currency_code": "USD",
                      "preferred_currency_amount": "1620.45",
                      "preferred_currency_code": "USD",
                      "payment_details": "Withdrawal to crypto wallet",
                      "payment_txn_id": null,
                      "score": 78,
                      "severity": "HIGH",
                      "decision_reason_code": "WALLET_HIGH_RISK",
                      "decision_reason_label": "Destination wallet flagged as high risk",
                      "vendor_data": "user-12345",
                      "metadata": {
                        "subject": {
                          "entity_type": "individual",
                          "vendor_data": "user-12345",
                          "full_name": "Maria Garcia",
                          "address": {},
                          "institution_details": {},
                          "device_context": {}
                        },
                        "counterparty": {}
                      },
                      "props": {
                        "order_id": "ord-9988"
                      },
                      "tags": [],
                      "parties": [
                        {
                          "uuid": "b1111111-2222-4333-8444-555555555555",
                          "role": "APPLICANT",
                          "entity_type": "individual",
                          "kind": "USER",
                          "vendor_data": "user-12345",
                          "full_name": "Maria Garcia",
                          "first_name": null,
                          "last_name": null,
                          "country_code": null,
                          "dob": null,
                          "address": {},
                          "institution_info": {},
                          "device": {},
                          "external_party_snapshot": null
                        }
                      ],
                      "payment_methods": [],
                      "documents": [],
                      "activities": [],
                      "alerts": [
                        {
                          "uuid": "a7b8c9d0-1234-4abc-9def-567890abcdef",
                          "title": "Destination wallet flagged as high risk",
                          "description": "Provider risk score exceeded the configured threshold.",
                          "severity": "HIGH",
                          "status": "OPEN",
                          "source": "RULE",
                          "metadata": {},
                          "created_at": "2026-05-17T08:42:12Z",
                          "due_at": null
                        }
                      ],
                      "rule_runs": [],
                      "provider_results": [],
                      "travel_rule": null,
                      "network_snapshot": null,
                      "remediation": null,
                      "action_required": null,
                      "cost_breakdown": null
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas lire les transactions de cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune transaction avec cet UUID n'existe pour l'application (supprimée, jamais créée, appartient à une autre application, ou le segment de chemin n'est pas un UUID valide).",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/transactions/sdk-token/": {
      "post": {
        "summary": "Émettre un token de transaction SDK",
        "description": "Émettez un token à portée limitée et à courte durée de vie que votre application transmet aux SDK Didit afin qu'ils puissent soumettre des transactions directement depuis l'appareil de l'utilisateur final via `POST /v1/transactions/`. Le token est lié à un `vendor_data` (votre identifiant d'utilisateur) : l'identité du sujet de chaque transaction soumise avec celui-ci est appliquée côté serveur à partir de cette liaison, de sorte qu'un client altéré ne peut pas soumettre pour le compte d'un autre utilisateur. Émettez les tokens depuis votre backend – n'intégrez jamais la clé API elle-même dans une application. Les alias en camelCase (`vendorData`, `ttlSeconds`, `maxUses`) sont également acceptés.",
        "operationId": "createTransactionSdkToken",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "create_sdk_token",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "vendor_data": {
                    "type": "string",
                    "description": "Votre identifiant interne pour l'utilisateur final auquel ce token est limité. Appliqué comme identité du sujet de chaque transaction soumise avec le token.",
                    "example": "user-042"
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "default": 900,
                    "maximum": 86400,
                    "description": "Durée de vie du token en secondes. Vaut par défaut 900 (15 minutes) ; maximum 86400 (24 heures)."
                  },
                  "max_uses": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Nombre maximal de soumissions réussies autorisées avec ce token. Omettre ou définir sur null pour des utilisations illimitées dans la limite du TTL."
                  }
                },
                "required": [
                  "vendor_data"
                ]
              },
              "example": {
                "vendor_data": "user-042",
                "ttl_seconds": 900,
                "max_uses": 3
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/transactions/sdk-token/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"vendor_data\": \"user-042\", \"ttl_seconds\": 900, \"max_uses\": 3}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.create_sdk_token(\n    vendor_data=\"user-042\",\n    ttl_seconds=900,\n    max_uses=3,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.createSdkToken({\n  vendor_data: \"user-042\",\n  ttl_seconds: 900,\n  max_uses: 3,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.CreateSDKToken(ctx, didit.TransactionsCreateSDKTokenParams{\n\tVendorData: \"user-042\",\n\tTTLSeconds: didit.Int(900),\n\tMaxUses:    didit.Int(3),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TransactionsCreateSdkTokenParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().createSdkToken(TransactionsCreateSdkTokenParams.builder()\n        .vendorData(\"user-042\")\n        .ttlSeconds(900L)\n        .maxUses(3L)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->createSdkToken([\n    'vendor_data' => 'user-042',\n    'ttl_seconds' => 900,\n    'max_uses' => 3,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.create_sdk_token(\n  vendor_data: \"user-042\",\n  ttl_seconds: 900,\n  max_uses: 3\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.CreateSdkTokenAsync(new TransactionsCreateSdkTokenParams\n{\n    VendorData = \"user-042\",\n    TtlSeconds = 900,\n    MaxUses = 3,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Le token généré. Transmettez `sdk_token` à votre application ; il authentifie les endpoints `/v1/transactions/` côté appareil via l'en-tête `X-Transaction-Token` jusqu'à `expires_at`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sdk_token": {
                      "type": "string",
                      "description": "Le token de transaction restreint à transmettre au SDK."
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Date et heure auxquelles le token cesse d'être accepté."
                    }
                  }
                },
                "example": {
                  "sdk_token": "q7Zt...urlsafe",
                  "expires_at": "2026-07-07T12:15:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Échec de la validation : `vendor_data` manquant, ou `ttl_seconds` en dehors de la plage autorisée.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing vendor_data": {
                    "value": {
                      "vendor_data": [
                        "This field is required."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid API Key": {
                    "value": {
                      "detail": "Invalid API Key."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/transactions/": {
      "post": {
        "summary": "Soumettre une transaction depuis un SDK",
        "description": "Endpoint orienté appareil appelé par les SDK Didit pour soumettre une transaction directement depuis l'appareil de l'utilisateur final. L'authentification repose sur un token avec portée issu de `POST /v3/transactions/sdk-token/` envoyé dans l'en-tête `X-Transaction-Token` au lieu d'une clé API, et l'endpoint prend en charge CORS afin que les navigateurs puissent l'appeler entre origines. Le payload utilise les alias réseau en camelCase indiqués ci-dessous (les méthodes `submitTransaction` du SDK le construisent pour vous). Trois garanties côté serveur : l'application est toujours issue du token ; l'identité du sujet (`externalUserId`) est toujours imposée à partir du `vendor_data` du token, de sorte que les valeurs de payload usurpées sont ignorées ; et les informations relatives à l'appareil (l'empreinte d'appareil du SDK ainsi que l'adresse IP et le user-agent dérivés par le serveur) sont automatiquement associées au sujet.",
        "operationId": "submitTransactionFromSdk",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "submit_from_device",
          "auth": "device_token",
          "server": false
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "TransactionTokenAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "txnId": {
                    "type": "string",
                    "description": "Votre identifiant unique pour cette transaction (correspond à `transaction_id`, 128 caractères maximum).",
                    "example": "wd-2026-07-07-0042"
                  },
                  "txnDate": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Date et heure auxquelles la transaction a eu lieu (correspond à `transaction_at`). Prend par défaut l'heure actuelle si ce champ est omis."
                  },
                  "zoneId": {
                    "type": "string",
                    "description": "Identifiant de fuseau horaire IANA (correspond à `time_zone`), par exemple `Europe/Madrid`."
                  },
                  "type": {
                    "type": "string",
                    "description": "Catégorie de transaction (correspond à `transaction_category`), par ex. `finance`, `kyc`, `travelRule`, `userPlatformEvent`, `gamblingBet`.",
                    "example": "travelRule"
                  },
                  "info": {
                    "type": "object",
                    "description": "Détails financiers principaux de la transaction (correspond à `transaction_details`).",
                    "required": [
                      "direction",
                      "amount",
                      "currency"
                    ],
                    "properties": {
                      "direction": {
                        "type": "string",
                        "description": "Direction par rapport au sujet. Insensible à la casse ; `in`/`out` sont acceptés comme alias. Renvoyée en majuscules (`INBOUND`/`OUTBOUND`).",
                        "example": "out"
                      },
                      "amount": {
                        "type": "number",
                        "description": "Montant de la transaction (jusqu'à 18 décimales). Une chaîne décimale est également acceptée et constitue le seul moyen de préserver plus d'environ 15 chiffres significatifs : un nombre JSON est d'abord analysé comme un flottant binaire, ainsi `0.123456789012345678` est stocké sous la forme `0.12345678901234568`.",
                        "example": 0.25
                      },
                      "currency": {
                        "type": "string",
                        "description": "Code devise. Tout code alphabétique ISO 4217 est accepté (par ex. `EUR`, `USD`, `NGN`), ainsi qu'un symbole d'actif crypto (par ex. `BTC`). Privilégiez un code actuellement en circulation. Tous les codes acceptés ne disposent pas d'un taux de change : lorsqu'aucun taux n'est disponible pour le code (par exemple l'unité de compte ISO `XSU`, ou un symbole crypto dont Didit n'établit pas le prix), la conversion automatique échoue et `preferred_currency_amount` est retourné nul, sauf si la requête a fourni un montant pré-converti `amountInDefaultCurrency`.",
                        "example": "ETH"
                      },
                      "currencyType": {
                        "type": "string",
                        "description": "Indique si la devise est `fiat` ou `crypto` (correspond à `currency_kind`)."
                      },
                      "amountInDefaultCurrency": {
                        "type": "number",
                        "nullable": true,
                        "description": "Montant pré-converti dans la devise par défaut (correspond à `amount_in_default_currency`). S'il est omis, une conversion de change automatique est tentée."
                      },
                      "defaultCurrencyCode": {
                        "type": "string",
                        "description": "Le code de devise par défaut pour le montant converti (correspond à `default_currency`). Tout code ISO 4217 actuellement en circulation."
                      },
                      "paymentDetails": {
                        "type": "string",
                        "nullable": true,
                        "description": "Référence ou mémo de paiement en texte libre (correspond à `payment_details`)."
                      },
                      "paymentTxnId": {
                        "type": "string",
                        "nullable": true,
                        "description": "Référence de paiement externe (correspond à `payment_reference_id`) ; le hachage de transaction on-chain pour les transactions en cryptomonnaies."
                      },
                      "type": {
                        "type": "string",
                        "nullable": true,
                        "description": "Sous-type de la transaction (correspond à `action_type`), par exemple `deposit`, `withdrawal`, `transfer`."
                      },
                      "cryptoParams": {
                        "type": "object",
                        "description": "Paramètres spécifiques à la crypto, par ex. `{\"crypto_chain\": \"ETH\"}`."
                      }
                    }
                  },
                  "subject": {
                    "type": "object",
                    "description": "L'objet (demandeur) de la transaction. `externalUserId` est ignoré ici : l'identité du sujet est toujours imposée à partir des `vendor_data` du token.",
                    "required": [
                      "fullName"
                    ],
                    "properties": {
                      "type": {
                        "type": "string",
                        "description": "Type d'entité (correspond à `entity_type`) : `individual` (par défaut) ou `company`."
                      },
                      "externalUserId": {
                        "type": "string",
                        "description": "Ignoré pour le sujet - appliqué côté serveur à partir du `vendor_data` du token."
                      },
                      "fullName": {
                        "type": "string",
                        "example": "Jane Doe"
                      },
                      "firstName": {
                        "type": "string"
                      },
                      "lastName": {
                        "type": "string"
                      },
                      "dob": {
                        "type": "string",
                        "format": "date",
                        "description": "Date de naissance (YYYY-MM-DD ; correspond à `date_of_birth`)."
                      },
                      "address": {
                        "type": "object",
                        "description": "Objet d'adresse avec `country` (ISO 3166-1 alpha-3), `town`, `state`, `street`, `post_code`."
                      },
                      "institutionInfo": {
                        "type": "object",
                        "description": "Informations sur l'établissement pour les participants institutionnels (correspond à `institution_details`)."
                      },
                      "device": {
                        "type": "object",
                        "description": "Contexte d'appareil explicite optionnel. Fusionné avec l'intelligence d'appareil capturée automatiquement ; les champs dérivés du serveur prévalent en cas de conflit."
                      },
                      "paymentMethod": {
                        "type": "object",
                        "description": "Moyen de paiement utilisé par le sujet (correspond à `payment_method`).",
                        "properties": {
                          "type": {
                            "type": "string",
                            "description": "Type de moyen de paiement (correspond à `method_type`), par ex. `bank_card`, `bank_account`, `crypto_wallet`, `ewallet`, `unhosted_wallet`, `other`."
                          },
                          "accountId": {
                            "type": "string",
                            "description": "Identifiant de compte (associé à `account_id`) : IBAN, empreinte de carte ou adresse de portefeuille."
                          },
                          "issuingCountry": {
                            "type": "string",
                            "description": "Code pays ISO 3166-1 alpha-3 de l'émetteur (correspond à `issuing_country`)."
                          }
                        }
                      }
                    }
                  },
                  "counterparty": {
                    "type": "object",
                    "description": "La contrepartie de la transaction (facultatif). Même structure que `subject` ; `externalUserId` a une signification ici.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "description": "Type d'entité (correspond à `entity_type`) : `individual` ou `company`."
                      },
                      "externalUserId": {
                        "type": "string",
                        "description": "Votre identifiant interne pour la contrepartie (correspond à `vendor_data`)."
                      },
                      "fullName": {
                        "type": "string"
                      },
                      "firstName": {
                        "type": "string"
                      },
                      "lastName": {
                        "type": "string"
                      },
                      "dob": {
                        "type": "string",
                        "format": "date"
                      },
                      "address": {
                        "type": "object"
                      },
                      "institutionInfo": {
                        "type": "object"
                      },
                      "device": {
                        "type": "object"
                      },
                      "paymentMethod": {
                        "type": "object",
                        "description": "Moyen de paiement utilisé par la contrepartie (correspond à `payment_method`). Sur les transactions travelRule, `type: \"unhosted_wallet\"` déclare le portefeuille de la contrepartie comme auto-hébergé : le transfert ignore le routage VASP-contrepartie, est créé directement sous `UNCONFIRMED_OWNERSHIP`, et (lorsque `auto_wallet_verification` est activé) une session de widget de propriété de portefeuille est générée automatiquement et renvoyée dans `action_required` afin que le SDK puisse la lancer.",
                        "properties": {
                          "type": {
                            "type": "string",
                            "description": "Type de moyen de paiement (correspond à `method_type`), par ex. `bank_card`, `bank_account`, `crypto_wallet`, `ewallet`, `unhosted_wallet`, `other`. Utilisez `unhosted_wallet` pour déclarer un portefeuille auto-hébergé pour la Travel Rule."
                          },
                          "accountId": {
                            "type": "string",
                            "description": "Identifiant de compte (associé à `account_id`) : IBAN, empreinte de carte ou adresse de portefeuille."
                          },
                          "issuingCountry": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  },
                  "props": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Paires clé-valeur personnalisées (correspond à `custom_properties`). Chaque clé peut être référencée dans les conditions de règles sous la forme `custom_values.<key>`."
                  },
                  "travelRule": {
                    "type": "object",
                    "description": "Détails de la Travel Rule (correspond à `travel_rule_details`). Lorsque la Travel Rule est activée pour l'application, Didit ignore tout `status` que vous envoyez et pilote lui-même l'échange.",
                    "required": [
                      "status"
                    ],
                    "properties": {
                      "status": {
                        "type": "string"
                      },
                      "protocol": {
                        "type": "string"
                      },
                      "required": {
                        "type": "boolean"
                      },
                      "obligationsCount": {
                        "type": "integer"
                      },
                      "originatorData": {
                        "type": "object"
                      },
                      "beneficiaryData": {
                        "type": "object"
                      },
                      "metadata": {
                        "type": "object"
                      }
                    }
                  },
                  "includeCryptoScreening": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Remplacement par transaction pour le filtrage par analyse de la blockchain crypto (correspond à `include_crypto_screening`)."
                  },
                  "fingerprint_v2": {
                    "type": "object",
                    "description": "Le payload d'empreinte d'appareil `didit-fp-v2`. Injecté automatiquement par les SDK ; pertinent uniquement lors de l'appel direct à l'API filaire."
                  }
                },
                "required": [
                  "txnId",
                  "type",
                  "info",
                  "subject"
                ]
              },
              "example": {
                "txnId": "wd-2026-07-07-0042",
                "type": "travelRule",
                "info": {
                  "direction": "out",
                  "amount": "0.25",
                  "currency": "ETH",
                  "currencyType": "crypto",
                  "cryptoParams": {
                    "crypto_chain": "ETH"
                  }
                },
                "subject": {
                  "fullName": "Jane Doe"
                },
                "counterparty": {
                  "fullName": "Ana Diaz",
                  "paymentMethod": {
                    "type": "unhosted_wallet",
                    "accountId": "0xBeneficiaryWallet01"
                  }
                },
                "travelRule": {
                  "status": "AWAITING_COUNTERPARTY",
                  "beneficiaryData": {
                    "wallet_address": "0xBeneficiaryWallet01",
                    "name": "Ana Diaz"
                  }
                },
                "includeCryptoScreening": true
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v1/transactions/ \\\n  -H 'X-Transaction-Token: SDK_TOKEN' -H 'Content-Type: application/json' \\\n  -d '{\"txnId\": \"wd-2026-07-07-0042\", \"type\": \"travelRule\", \"info\": {\"direction\": \"out\", \"amount\": \"0.25\", \"currency\": \"ETH\", \"currencyType\": \"crypto\"}, \"subject\": {\"fullName\": \"Jane Doe\"}, \"counterparty\": {\"fullName\": \"Ana Diaz\", \"paymentMethod\": {\"type\": \"unhosted_wallet\", \"accountId\": \"0xBeneficiaryWallet01\"}}, \"travelRule\": {\"status\": \"AWAITING_COUNTERPARTY\", \"beneficiaryData\": {\"wallet_address\": \"0xBeneficiaryWallet01\", \"name\": \"Ana Diaz\"}}, \"includeCryptoScreening\": true}'"
          },
          {
            "lang": "javascript",
            "label": "Web SDK",
            "source": "import { DiditSdk } from '@didit-protocol/sdk-web';\n\nconst result = await DiditSdk.shared.submitTransaction({\n  transactionToken: sdkToken,\n  transaction: {\n    txnId: 'wd-2026-07-07-0042',\n    category: 'travelRule',\n    details: { direction: 'out', amount: '0.25', currency: 'ETH', currencyType: 'crypto' },\n    subject: { fullName: 'Jane Doe' },\n    counterparty: { fullName: 'Ana Diaz', paymentMethod: { type: 'unhosted_wallet', accountId: '0xBeneficiaryWallet01' } },\n    travelRule: { status: 'AWAITING_COUNTERPARTY', beneficiaryData: { wallet_address: '0xBeneficiaryWallet01', name: 'Ana Diaz' } },\n    includeCryptoScreening: true\n  },\n  onActionCompleted: (refreshed) => console.log(refreshed.status)\n});"
          }
        ],
        "responses": {
          "201": {
            "description": "Transaction soumise et surveillée. Même structure de détails que `GET /v3/transactions/{transaction_id}/`, y compris le bloc `action_required` lorsque l'utilisateur final doit effectuer une action de suivi (les SDK la lancent automatiquement par défaut).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionDetail"
                },
                "examples": {
                  "Wallet ownership required": {
                    "value": {
                      "uuid": "22222222-3333-4444-5555-666666666666",
                      "txn_id": "wd-2026-07-07-0042",
                      "transaction_type": "travelRule",
                      "direction": "OUTBOUND",
                      "status": "APPROVED",
                      "amount": "0.25",
                      "currency": "ETH",
                      "travel_rule": {
                        "uuid": "33333333-4444-5555-6666-777777777777",
                        "status": "UNCONFIRMED_OWNERSHIP",
                        "required": true
                      },
                      "action_required": {
                        "type": "wallet_ownership",
                        "url": "https://verify.didit.me/wallet-ownership/3s9x...urlsafe",
                        "widget_session_id": "77777777-8888-9999-aaaa-bbbbbbbbbbbb",
                        "expires_at": "2026-07-07T13:00:00Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Échec de validation (champs obligatoires manquants, `txnId` en doublon, catégorie inconnue).",
            "content": {
              "application/json": {
                "examples": {
                  "Missing fields": {
                    "value": {
                      "transaction_details": {
                        "currency": [
                          "This field is required."
                        ]
                      }
                    }
                  },
                  "Duplicate txnId": {
                    "value": {
                      "transaction_id": [
                        "A transaction with this transaction_id already exists."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Le token de transaction a été rejeté : manquant, inconnu, révoqué, dépassant son `max_uses`, ou expiré. Les réponses pour token expiré contiennent toujours le mot `expired` dans le détail, ce qui permet aux SDK de distinguer les erreurs `expired_token` de `invalid_token`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "Invalid transaction token."
                    }
                  },
                  "Expired token": {
                    "value": {
                      "detail": "Transaction token expired."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Une autre requête avec le même `txnId` a créé la transaction pendant le traitement de celle-ci, de sorte qu'une seule des deux soumissions simultanées réussit. Lisez la transaction existante au lieu de la soumettre à nouveau.",
            "content": {
              "application/json": {
                "examples": {
                  "Concurrent duplicate": {
                    "value": {
                      "detail": "A transaction with this transaction_id already exists."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/transactions/{transaction_id}/": {
      "get": {
        "summary": "Obtenir une transaction depuis un SDK",
        "description": "Endpoint de lecture orienté appareil, authentifié avec le même `X-Transaction-Token` utilisé pour la soumission. Les SDK l'interrogent périodiquement après l'exécution d'un flux d'action lancé automatiquement ou après la fermeture de sa fenêtre, afin que l'état final ne dépende jamais d'une seule notification. Renvoie les mêmes détails de transaction que la réponse de soumission, y compris le bloc `action_required` actuel (`null` une fois l'action résolue).",
        "operationId": "getTransactionFromSdk",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "retrieve_from_device",
          "auth": "device_token",
          "server": false
        },
        "tags": [
          "Transactions"
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID de transaction stable attribué par Didit (le `uuid` de la réponse de soumission, **et non** votre `txnId`).",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "22222222-3333-4444-5555-666666666666"
          }
        ],
        "security": [
          {
            "TransactionTokenAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v1/transactions/22222222-3333-4444-5555-666666666666/' \\\n  -H 'X-Transaction-Token: SDK_TOKEN'"
          }
        ],
        "responses": {
          "200": {
            "description": "Le détail complet de la transaction, y compris `action_required` (`null` une fois l'action en attente résolue).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionDetail"
                }
              }
            }
          },
          "401": {
            "description": "Le token de transaction a été rejeté : manquant, inconnu, révoqué, dépassant son `max_uses`, ou expiré.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired token": {
                    "value": {
                      "detail": "Transaction token expired."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune transaction avec cet UUID n'existe pour l'application du token, ou le segment de chemin n'est pas un UUID valide.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/businesses/": {
      "get": {
        "summary": "Lister les entreprises",
        "description": "Lister les [entreprises](/entities/businesses) que Didit regroupe à partir des sessions KYB partageant le même `vendor_data` (chaîne libre, et NON un UUID), ainsi que les entreprises créées via l'API. Paginé, ordonné par `last_session_at` décroissant. Cet endpoint ne prend pas en charge les paramètres de filtrage ou de recherche — récupérez les pages et filtrez côté client.",
        "operationId": "list_businesses",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "description": "Taille de page. Vaut 50 par défaut si omis. Aucun maximum n'est imposé, mais conservez des pages de petite taille pour limiter la latence."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "description": "Décalage de départ (base zéro) du premier enregistrement à retourner. Privilégiez l'utilisation de l'URL `next` de la page précédente plutôt que de le calculer manuellement."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/businesses/?limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.businesses.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.businesses.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Businesses.ListAutoPaging(ctx, didit.BusinessesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.businesses().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->businesses->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.businesses.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Businesses.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginée des entreprises avec statut, décompte des sessions et détail des fonctionnalités.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de lignes correspondantes — exact jusqu'à 100, plafonné à 100 au-delà pour des raisons de performance. Ne l'utilisez pas pour détecter la dernière page ; fiez-vous plutôt au fait que `next` soit `null`."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BusinessListItem"
                      }
                    }
                  }
                },
                "examples": {
                  "Example": {
                    "value": {
                      "count": 1,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "didit_internal_id": "a1b2c3d4-e5f6-4890-abcd-ef1234567890",
                          "vendor_data": "company-123",
                          "display_name": null,
                          "legal_name": "Acme Trading Ltd",
                          "registration_number": "12345678",
                          "country_code": "GB",
                          "effective_name": "Acme Trading Ltd",
                          "status": "ACTIVE",
                          "session_count": 2,
                          "approved_count": 1,
                          "declined_count": 0,
                          "in_review_count": 1,
                          "features": {
                            "KYB": "Approved"
                          },
                          "features_list": [
                            {
                              "feature": "KYB",
                              "status": "Approved"
                            }
                          ],
                          "last_session_at": "2026-03-15T10:30:00Z",
                          "last_activity_at": "2026-03-15T10:30:00Z",
                          "first_session_at": "2026-01-10T08:00:00Z",
                          "tags": [
                            {
                              "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                              "name": "VIP",
                              "color": "#2567FF"
                            }
                          ],
                          "created_at": "2026-01-10T08:00:00Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas lister les entreprises pour cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/customization/": {
      "get": {
        "summary": "Obtenir la personnalisation de marque",
        "description": "Renvoie la personnalisation en marque blanche pour l'application résolue à partir de la clé API : couleurs, polices, rayons de bordure, URL de logos et options d'UI/UX. Les paramètres de domaine personnalisé et d'e-mail en marque blanche sont gérés uniquement dans la Business Console et ne font pas partie de cette réponse.",
        "operationId": "get_customization",
        "x-didit-sdk": {
          "resource": "customization",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Customization"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/customization/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.customization.retrieve()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.customization.retrieve();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Customization.Retrieve(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.customization().retrieve();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->customization->retrieve();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.customization.retrieve\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Customization.RetrieveAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Personnalisation actuelle de l'image de marque pour l'application.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrandingCustomization"
                },
                "examples": {
                  "Default branding": {
                    "value": {
                      "color_primary": "#000000",
                      "color_secondary": "#9DA1A1",
                      "color_background": "#FFFFFF",
                      "color_panel": "#2567FF",
                      "color_panel_10": "#1A1A1A",
                      "color_on_panel_1": "#9DA1A1",
                      "color_on_panel_2": "#F4F4F6",
                      "color_on_background": "#000000",
                      "color_button_1": "#2567FF",
                      "color_button_2": "#F8F8F8",
                      "color_button_text_1": "#FFFFFF",
                      "color_button_text_2": "#000000",
                      "color_pill_text": "#111827",
                      "border_radius_panel": 10,
                      "border_radius_buttons": 12,
                      "font_family": "Inter",
                      "font_weight": "regular",
                      "font_url": "https://fonts.googleapis.com/css2?family=Inter",
                      "logo_square": null,
                      "logo_rectangular": null,
                      "logo_rectangular_dark": null,
                      "favicon": null,
                      "app_public_name": "Acme Verify",
                      "privacy_policy_url": "https://acme.com/privacy",
                      "skip_welcome_screen": false,
                      "disable_login_with_didit": false,
                      "hide_progress_bar": false,
                      "callback_seconds": 3
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour la personnalisation de marque",
        "description": "Mise à jour partielle de l'image de marque en marque blanche de l'application. Envoyez `application/json` pour modifier les couleurs, polices, arrondis et options d'interface utilisateur, ou `multipart/form-data` pour importer des images de logo. Seuls les champs inclus sont modifiés. Le domaine personnalisé et l'e-mail en marque blanche ne peuvent pas être configurés via cet endpoint — utilisez la Business Console pour cela.",
        "operationId": "update_customization",
        "x-didit-sdk": {
          "resource": "customization",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Customization"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BrandingCustomizationUpdate"
              },
              "examples": {
                "Update colors and font": {
                  "summary": "Modifier les couleurs de marque et la police",
                  "value": {
                    "color_primary": "#123456",
                    "color_button_1": "#2567FF",
                    "font_family": "AR One Sans",
                    "border_radius_buttons": 16
                  }
                },
                "Update UI options": {
                  "summary": "Modifier le nom public et les options de flux",
                  "value": {
                    "app_public_name": "Acme Verify",
                    "privacy_policy_url": "https://acme.com/privacy",
                    "skip_welcome_screen": true,
                    "hide_progress_bar": true,
                    "callback_seconds": 5
                  }
                },
                "Remove a logo": {
                  "summary": "Supprimer le logo rectangulaire actuel",
                  "value": {
                    "delete_logo_rectangular": true
                  }
                },
                "Remove the dark-mode logo": {
                  "summary": "Supprimer le logo actuel du mode sombre",
                  "value": {
                    "delete_logo_rectangular_dark": true
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "description": "Utilisez multipart/form-data uniquement pour téléverser des images de logo. Les champs d'image de marque ci-dessus peuvent également être envoyés sous forme de champs de formulaire dans la même requête.",
                "properties": {
                  "image_square": {
                    "type": "string",
                    "format": "binary",
                    "description": "Logo carré (format 1:1). PNG, JPG ou WebP, au moins 512 px sur le côté le plus long, au maximum **1 MB**."
                  },
                  "image_rectangular": {
                    "type": "string",
                    "format": "binary",
                    "description": "Logo rectangulaire (format 2:1). PNG, JPG ou WebP, au moins 512 px sur le côté le plus long, au maximum **1 MB**."
                  },
                  "image_rectangular_dark": {
                    "type": "string",
                    "format": "binary",
                    "description": "Logo rectangulaire pour le mode sombre (format 2:1), affiché sur fond sombre. PNG, JPG ou WebP, au moins 512 px sur le côté le plus long, au maximum **1 MB**. Renvoyé sous la forme `logo_rectangular_dark`."
                  },
                  "image_favicon": {
                    "type": "string",
                    "format": "binary",
                    "description": "Image du favicon. **500 KB** max."
                  }
                }
              },
              "example": {
                "image_rectangular": "(binary PNG logo, 2:1)",
                "image_rectangular_dark": "(binary PNG logo for dark mode, 2:1)",
                "image_favicon": "(binary favicon)"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/customization/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"color_primary\": \"#123456\", \"font_family\": \"AR One Sans\"}'"
          },
          {
            "lang": "curl",
            "label": "curl (logo upload)",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/customization/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'image_rectangular=@logo.png' \\\n  -F 'image_rectangular_dark=@logo-dark.png' \\\n  -F 'image_favicon=@favicon.ico'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.customization.update(\n    image_rectangular=open(\"image_rectangular.jpg\", \"rb\"),\n    image_rectangular_dark=open(\"image_rectangular_dark.jpg\", \"rb\"),\n    image_favicon=open(\"image_favicon.jpg\", \"rb\"),\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.customization.update({\n  image_rectangular: await fileFromPath(\"image_rectangular.jpg\"),\n  image_rectangular_dark: await fileFromPath(\"image_rectangular_dark.jpg\"),\n  image_favicon: await fileFromPath(\"image_favicon.jpg\"),\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Customization.Update(ctx, didit.CustomizationUpdateParams{\n\tImageRectangular:     didit.Some(didit.FileFromPath(\"image_rectangular.jpg\")),\n\tImageRectangularDark: didit.Some(didit.FileFromPath(\"image_rectangular_dark.jpg\")),\n\tImageFavicon:         didit.Some(didit.FileFromPath(\"image_favicon.jpg\")),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\nimport me.didit.types.CustomizationUpdateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.customization().update(CustomizationUpdateParams.builder()\n        .imageRectangular(Path.of(\"image_rectangular.jpg\"))\n        .imageRectangularDark(Path.of(\"image_rectangular_dark.jpg\"))\n        .imageFavicon(Path.of(\"image_favicon.jpg\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->customization->update([\n    'image_rectangular' => File::fromPath('image_rectangular.jpg'),\n    'image_rectangular_dark' => File::fromPath('image_rectangular_dark.jpg'),\n    'image_favicon' => File::fromPath('image_favicon.jpg'),\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.customization.update(\n  image_rectangular: Pathname(\"image_rectangular.jpg\"),\n  image_rectangular_dark: Pathname(\"image_rectangular_dark.jpg\"),\n  image_favicon: Pathname(\"image_favicon.jpg\")\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Customization.UpdateAsync(new CustomizationUpdateParams\n{\n    ImageRectangular = FileUpload.FromPath(\"image_rectangular.jpg\"),\n    ImageRectangularDark = FileUpload.FromPath(\"image_rectangular_dark.jpg\"),\n    ImageFavicon = FileUpload.FromPath(\"image_favicon.jpg\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Image de marque mise à jour. L'objet complet d'image de marque est renvoyé (tous les champs, pas seulement ceux modifiés).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrandingCustomization"
                },
                "examples": {
                  "Updated": {
                    "value": {
                      "color_primary": "#123456",
                      "color_secondary": "#9DA1A1",
                      "color_background": "#FFFFFF",
                      "color_panel": "#2567FF",
                      "color_panel_10": "#1A1A1A",
                      "color_on_panel_1": "#9DA1A1",
                      "color_on_panel_2": "#F4F4F6",
                      "color_on_background": "#000000",
                      "color_button_1": "#2567FF",
                      "color_button_2": "#F8F8F8",
                      "color_button_text_1": "#FFFFFF",
                      "color_button_text_2": "#000000",
                      "color_pill_text": "#111827",
                      "border_radius_panel": 10,
                      "border_radius_buttons": 16,
                      "font_family": "AR One Sans",
                      "font_weight": "400",
                      "font_url": "https://fonts.googleapis.com/css2?family=AR+One+Sans",
                      "logo_square": null,
                      "logo_rectangular": "https://cdn.didit.me/white_label/logo_rectangular/...",
                      "logo_rectangular_dark": null,
                      "favicon": null,
                      "app_public_name": "Acme Verify",
                      "privacy_policy_url": "https://acme.com/privacy",
                      "skip_welcome_screen": true,
                      "disable_login_with_didit": false,
                      "hide_progress_bar": false,
                      "callback_seconds": 3
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide. Par exemple : une couleur hexadécimale malformée, une famille ou graisse de police inconnue, un champ réservé à la Business Console (`domain`, `from_email`, `verify_domain`, `force_remove_domain`, `verify_email_domain`, `force_remove_email_domain`, ainsi que leurs équivalents en lecture seule), ou un import de logo qui n'est pas une image PNG, JPG ou WebP, fait moins de 512 px sur son côté le plus long, dépasse 1 Mo, ou a un rapport hauteur/largeur incorrect. Également renvoyé lors de la définition de `disable_login_with_didit` à `false` alors qu'un domaine personnalisé est configuré.",
            "content": {
              "application/json": {
                "examples": {
                  "Bad color": {
                    "value": {
                      "color_primary": [
                        "Invalid color format. Use '#RRGGBB' or '#RRGGBBAA' format."
                      ]
                    }
                  },
                  "Bad logo": {
                    "value": {
                      "image_rectangular": [
                        "Image aspect ratio must be 2:1. Got 1024x1024 image dimensions"
                      ]
                    }
                  },
                  "Unsupported logo format": {
                    "summary": "Pas une image PNG, JPG ou WebP (un SVG, par exemple)",
                    "value": {
                      "image_rectangular_dark": [
                        "Upload a PNG, JPG or WebP image."
                      ]
                    }
                  },
                  "Logo too small": {
                    "summary": "Moins de 512 px sur le côté long",
                    "value": {
                      "image_rectangular": [
                        "Image must be at least 512 px on its long side. Got 400x200 image dimensions"
                      ]
                    }
                  },
                  "Logo too large": {
                    "summary": "Supérieur à 1 Mo",
                    "value": {
                      "image_square": [
                        "File size should not exceed 1 MB"
                      ]
                    }
                  },
                  "Console-only field": {
                    "value": {
                      "domain": [
                        "Manage this field in the Business Console."
                      ]
                    }
                  },
                  "Bad font weight": {
                    "value": {
                      "font_weight": [
                        "Font weight 950 is not available for Inter. Available weights are: 100, 200, 300, 400, 500, 600, 700, 800, 900"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, mal formée, expirée ou limitée à une application différente. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid token": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Réessayez avec une temporisation exponentielle."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/businesses/{vendor_data}/": {
      "get": {
        "summary": "Obtenir l'entreprise",
        "description": "Récupérer une [entreprise](/entities/businesses) par `vendor_data` (correspondance exacte). Ajoute `metadata` et `updated_at` à la vue de liste. Les entreprises supprimées renvoient une erreur 404.",
        "operationId": "get_business",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "vendor_data",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Votre identifiant unique pour l'entreprise — chaîne libre (PAS un UUID), mise en correspondance exactement telle qu'envoyée.",
            "example": "company-123"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/businesses/company-123/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.businesses.retrieve(\n    \"company-123\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.businesses.retrieve(\"company-123\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.Retrieve(ctx, \"company-123\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.businesses().retrieve(\"company-123\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->businesses->retrieve('company-123');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.businesses.retrieve(\"company-123\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.RetrieveAsync(\"company-123\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détails complets de l'entreprise, y compris les métadonnées et les données agrégées de session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessDetailItem"
                },
                "examples": {
                  "Active business": {
                    "value": {
                      "didit_internal_id": "a1b2c3d4-e5f6-4890-abcd-ef1234567890",
                      "vendor_data": "company-123",
                      "display_name": null,
                      "legal_name": "Acme Trading Ltd",
                      "registration_number": "12345678",
                      "country_code": "GB",
                      "effective_name": "Acme Trading Ltd",
                      "status": "ACTIVE",
                      "session_count": 2,
                      "approved_count": 1,
                      "declined_count": 0,
                      "in_review_count": 1,
                      "features": {
                        "KYB": "Approved"
                      },
                      "features_list": [
                        {
                          "feature": "KYB",
                          "status": "Approved"
                        }
                      ],
                      "last_session_at": "2026-03-15T10:30:00Z",
                      "last_activity_at": "2026-03-15T10:30:00Z",
                      "first_session_at": "2026-01-10T08:00:00Z",
                      "tags": [
                        {
                          "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                          "name": "VIP",
                          "color": "#2567FF"
                        }
                      ],
                      "created_at": "2026-01-10T08:00:00Z",
                      "metadata": {
                        "industry": "fintech"
                      },
                      "updated_at": "2026-03-15T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas lire les entreprises de cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune entreprise (non supprimée) avec le `vendor_data` fourni n'existe pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour l'entreprise",
        "description": "Mise à jour partielle d'une entreprise : `display_name`, `legal_name`, `registration_number`, `country_code`, `status`, `metadata`. `metadata` est entièrement remplacé. Définir `status` sur `BLOCKED` ajoute le `vendor_data` à la liste de blocage du système ; quitter l'état `BLOCKED` retire cette entrée. Chaque modification est enregistrée dans l'activité de l'entreprise : un changement de statut avec le `reason` facultatif, et une modification de `display_name`, `legal_name`, `registration_number`, `country_code` ou `metadata` en tant que mise à jour du profil.",
        "operationId": "update_business",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "vendor_data",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Votre identifiant unique pour l'entreprise (chaîne libre, PAS un UUID).",
            "example": "company-123"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Corps de la requête de mise à jour partielle. Ne fournissez que les champs que vous souhaitez modifier.",
                "properties": {
                  "display_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "Nom d'affichage convivial affiché dans la console (prend le pas sur `legal_name` pour l'affichage de l'interface utilisateur)."
                  },
                  "legal_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "Raison sociale officielle issue du registre ou saisie manuelle."
                  },
                  "registration_number": {
                    "type": "string",
                    "nullable": true,
                    "description": "Numéro d'immatriculation ou de constitution de l'entreprise."
                  },
                  "country_code": {
                    "type": "string",
                    "nullable": true,
                    "description": "Pays de constitution (ISO 3166-1 alpha-2, par ex. `GB`, `US`)."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "ACTIVE",
                      "FLAGGED",
                      "BLOCKED"
                    ],
                    "description": "Statut du cycle de vie de l'entreprise. Définir `BLOCKED` ajoute automatiquement le `vendor_data` à la liste de blocage du système ; quitter `BLOCKED` supprime cette entrée de la liste de blocage."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "Objet JSON arbitraire que vous associez à l'entreprise. **Remplace complètement** les métadonnées existantes lors de la mise à jour — fusionnez côté client si vous souhaitez uniquement ajouter des clés."
                  },
                  "reason": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 1000,
                    "description": "Raison pour laquelle le statut a changé. Enregistrée sur l'entrée de changement de statut dans **Activité** de l'entreprise au sein de la Business Console, uniquement lorsque le statut change réellement. Les webhooks ne la transmettent pas."
                  }
                }
              },
              "examples": {
                "Update name": {
                  "summary": "Mettre à jour le nom d'affichage",
                  "value": {
                    "display_name": "Acme Corp"
                  }
                },
                "Flag for review": {
                  "summary": "Basculer le statut",
                  "value": {
                    "status": "FLAGGED"
                  }
                },
                "Add metadata": {
                  "summary": "Remplacer le JSON des métadonnées",
                  "value": {
                    "metadata": {
                      "industry": "fintech",
                      "risk_level": "low"
                    }
                  }
                },
                "Fix registry data": {
                  "summary": "Champs extraits corrects",
                  "value": {
                    "legal_name": "Acme Trading International Ltd",
                    "registration_number": "12345678",
                    "country_code": "GB"
                  }
                },
                "Flag with reason": {
                  "summary": "Signaler l'entreprise et enregistrer le motif",
                  "value": {
                    "status": "FLAGGED",
                    "reason": "Ownership structure under review"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/businesses/company-123/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"display_name\": \"Acme Corp\", \"status\": \"FLAGGED\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.businesses.update(\n    \"company-123\",\n    display_name=\"Acme Corp\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.businesses.update(\"company-123\", {\n  display_name: \"Acme Corp\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.Update(ctx, \"company-123\", didit.BusinessesUpdateParams{\n\tDisplayName: didit.String(\"Acme Corp\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.BusinessesUpdateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.businesses().update(\"company-123\", BusinessesUpdateParams.builder()\n        .displayName(\"Acme Corp\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->businesses->update('company-123', [\n    'display_name' => 'Acme Corp',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.businesses.update(\n  \"company-123\",\n  display_name: \"Acme Corp\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.UpdateAsync(\"company-123\", new BusinessesUpdateParams\n{\n    DisplayName = \"Acme Corp\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Entreprise mise à jour. L'enregistrement complet et mis à jour de l'entreprise est renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessDetailItem"
                },
                "examples": {
                  "Updated": {
                    "value": {
                      "didit_internal_id": "a1b2c3d4-e5f6-4890-abcd-ef1234567890",
                      "vendor_data": "company-123",
                      "display_name": "Acme Corp",
                      "legal_name": "Acme Trading Ltd",
                      "registration_number": "12345678",
                      "country_code": "GB",
                      "effective_name": "Acme Corp",
                      "status": "FLAGGED",
                      "session_count": 2,
                      "approved_count": 1,
                      "declined_count": 0,
                      "in_review_count": 1,
                      "features": {
                        "KYB": "Approved"
                      },
                      "features_list": [
                        {
                          "feature": "KYB",
                          "status": "Approved"
                        }
                      ],
                      "last_session_at": "2026-03-15T10:30:00Z",
                      "last_activity_at": "2026-03-15T10:30:00Z",
                      "first_session_at": "2026-01-10T08:00:00Z",
                      "tags": [
                        {
                          "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                          "name": "VIP",
                          "color": "#2567FF"
                        }
                      ],
                      "created_at": "2026-01-10T08:00:00Z",
                      "metadata": {
                        "industry": "fintech",
                        "risk_level": "low"
                      },
                      "updated_at": "2026-03-15T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide : généralement un `status` inconnu, des `metadata` malformées ou une `reason` de plus de 1000 caractères.",
            "content": {
              "application/json": {
                "examples": {
                  "Bad status": {
                    "value": {
                      "status": [
                        "Invalid status. Valid options are: ACTIVE, FLAGGED, BLOCKED"
                      ]
                    }
                  },
                  "Bad metadata": {
                    "value": {
                      "metadata": [
                        "Metadata must be a JSON object."
                      ]
                    }
                  },
                  "Reason too long": {
                    "value": {
                      "reason": [
                        "Ensure this field has no more than 1000 characters."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas mettre à jour d'entreprises pour cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune entreprise (non supprimée) avec le `vendor_data` fourni n'existe pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/businesses/{vendor_data}/update-status/": {
      "patch": {
        "summary": "Mettre à jour le statut de l'entreprise",
        "description": "Basculer uniquement le `status` de cycle de vie d'une entreprise : `ACTIVE`, `FLAGGED` ou `BLOCKED` (pas les statuts de session). `BLOCKED` ajoute le `vendor_data` à la liste de blocage du système ; quitter l'état `BLOCKED` supprime cette entrée. Chaque modification est enregistrée dans l'activité de l'entreprise, avec le `reason` facultatif. Envoyer le statut actuel ne change rien et n'enregistre aucun `reason`. Le webhook `business.status.updated` ne transmet pas `reason`.",
        "operationId": "update_business_status",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "update_status",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "vendor_data",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Votre identifiant unique pour l'entreprise (chaîne libre, PAS un UUID).",
            "example": "company-123"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EntityStatusUpdateRequest"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 1000,
                        "description": "Raison pour laquelle le statut a changé. Enregistrée sur l'entrée de changement de statut dans **Activité** de l'entreprise au sein de la Business Console, uniquement lorsque le statut change réellement. Les webhooks ne la transmettent pas."
                      }
                    }
                  }
                ]
              },
              "examples": {
                "Flag": {
                  "summary": "Signaler l'entreprise pour examen",
                  "value": {
                    "status": "FLAGGED"
                  }
                },
                "Block": {
                  "summary": "Bloquer l'entreprise (ajoute à la liste de blocage du système)",
                  "value": {
                    "status": "BLOCKED"
                  }
                },
                "Reactivate": {
                  "summary": "Réactiver l'entreprise",
                  "value": {
                    "status": "ACTIVE"
                  }
                },
                "Block with reason": {
                  "summary": "Bloquer l'entreprise et consigner le motif",
                  "value": {
                    "status": "BLOCKED",
                    "reason": "Registry shows the company dissolved"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/businesses/company-123/update-status/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"status\": \"BLOCKED\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.businesses.update_status(\n    \"company-123\",\n    status=\"FLAGGED\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.businesses.updateStatus(\"company-123\", {\n  status: \"FLAGGED\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.UpdateStatus(ctx, \"company-123\", didit.BusinessesUpdateStatusParams{\n\tStatus: \"FLAGGED\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.BusinessesUpdateStatusParams;\nimport me.didit.types.EntityStatusUpdateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.businesses().updateStatus(\"company-123\", BusinessesUpdateStatusParams.builder()\n        .status(EntityStatusUpdateRequest.Status.of(\"FLAGGED\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->businesses->updateStatus('company-123', [\n    'status' => 'FLAGGED',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.businesses.update_status(\n  \"company-123\",\n  status: \"FLAGGED\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.UpdateStatusAsync(\"company-123\", new BusinessesUpdateStatusParams\n{\n    Status = \"FLAGGED\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Statut de l'entreprise mis à jour. L'enregistrement complet de l'entreprise est renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessDetailItem"
                },
                "examples": {
                  "Blocked": {
                    "value": {
                      "didit_internal_id": "a1b2c3d4-e5f6-4890-abcd-ef1234567890",
                      "vendor_data": "company-123",
                      "display_name": null,
                      "legal_name": "Acme Trading Ltd",
                      "registration_number": "12345678",
                      "country_code": "GB",
                      "effective_name": "Acme Trading Ltd",
                      "status": "BLOCKED",
                      "session_count": 2,
                      "approved_count": 1,
                      "declined_count": 0,
                      "in_review_count": 1,
                      "features": {
                        "KYB": "Approved"
                      },
                      "features_list": [
                        {
                          "feature": "KYB",
                          "status": "Approved"
                        }
                      ],
                      "last_session_at": "2026-03-15T10:30:00Z",
                      "last_activity_at": "2026-03-15T10:30:00Z",
                      "first_session_at": "2026-01-10T08:00:00Z",
                      "tags": [
                        {
                          "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                          "name": "VIP",
                          "color": "#2567FF"
                        }
                      ],
                      "created_at": "2026-01-10T08:00:00Z",
                      "metadata": {
                        "industry": "fintech"
                      },
                      "updated_at": "2026-03-15T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`status` manquant ou invalide, ou un `reason` de plus de 1000 caractères.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing status": {
                    "value": {
                      "status": [
                        "This field is required."
                      ]
                    }
                  },
                  "Bad status": {
                    "value": {
                      "status": [
                        "Invalid status. Valid options are: ACTIVE, FLAGGED, BLOCKED"
                      ]
                    }
                  },
                  "Reason too long": {
                    "value": {
                      "reason": [
                        "Ensure this field has no more than 1000 characters."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas mettre à jour d'entreprises pour cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune entreprise (non supprimée) avec le `vendor_data` fourni n'existe pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/businesses/delete/": {
      "post": {
        "summary": "Supprimer des entreprises par lot",
        "description": "**Supprimer définitivement** des entreprises — cette action ne peut pas être annulée. Pour bloquer, préférez [Update Business Status](#patch-/v3/businesses/-vendor_data-/update-status/) avec `BLOCKED`.\n\n**Rapports réglementaires déposés :** si les données sélectionnées figurent dans un rapport réglementaire finalisé, l'ensemble de la requête est refusé avec `409` et rien n'est supprimé. Le corps utilise `code: in_filed_report` et nomme chaque rapport avec `uuid`, `report_number`, `report_type` et `case_uuid`. Supprimez les rapports, puis réessayez la requête.",
        "operationId": "batch_delete_businesses",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "batch_delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Businesses"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Fournissez `vendor_data_list`, `didit_internal_id_list` ou `delete_all: true`. Ordre de priorité si plusieurs sont envoyés : `delete_all` > `vendor_data_list` > `didit_internal_id_list` (seul le sélecteur ayant la priorité la plus élevée est utilisé).",
                "properties": {
                  "vendor_data_list": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Vos propres identifiants à supprimer, mis en correspondance exacte avec ceux transmis."
                  },
                  "didit_internal_id_list": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "UUID internes Didit (`didit_internal_id`) à supprimer."
                  },
                  "delete_all": {
                    "type": "boolean",
                    "default": false,
                    "description": "Si `true`, supprime toutes les entreprises de l'application. Ne peut pas être combiné avec les sélecteurs de liste."
                  }
                }
              },
              "examples": {
                "Specific businesses": {
                  "summary": "Supprimer par vendor_data",
                  "value": {
                    "vendor_data_list": [
                      "company-123",
                      "company-456"
                    ]
                  }
                },
                "Specific internal IDs": {
                  "summary": "Supprimer par didit_internal_id",
                  "value": {
                    "didit_internal_id_list": [
                      "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "b2c3d4e5-f6a7-8901-bcde-f12345678901"
                    ]
                  }
                },
                "All businesses": {
                  "summary": "Effacer toutes les entreprises de cette application",
                  "value": {
                    "delete_all": true
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/businesses/delete/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"vendor_data_list\": [\"company-123\", \"company-456\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.businesses.batch_delete(\n    vendor_data_list=[\"company-123\", \"company-456\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.businesses.batchDelete({\n  vendor_data_list: [\"company-123\", \"company-456\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.BatchDelete(ctx, didit.BusinessesBatchDeleteParams{\n\tVendorDataList: didit.Some([]string{\"company-123\", \"company-456\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.BusinessesBatchDeleteParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.businesses().batchDelete(BusinessesBatchDeleteParams.builder()\n        .vendorDataList(List.of(\"company-123\", \"company-456\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->businesses->batchDelete([\n    'vendor_data_list' => ['company-123', 'company-456'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.businesses.batch_delete(vendor_data_list: [\"company-123\", \"company-456\"])\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.BatchDeleteAsync(new BusinessesBatchDeleteParams\n{\n    VendorDataList = new string[] { \"company-123\", \"company-456\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Entreprises supprimées. Renvoie le nombre de lignes effectivement supprimées.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "integer",
                      "description": "Nombre d'entreprises supprimées (exclut les valeurs de vendor_data qui ne correspondaient à rien)."
                    }
                  }
                },
                "examples": {
                  "Deleted some": {
                    "value": {
                      "deleted": 2
                    }
                  },
                  "Nothing matched": {
                    "value": {
                      "deleted": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Aucun sélecteur fourni (tous les éléments `vendor_data_list`, `didit_internal_id_list` et `delete_all` sont manquants ou vides). Le corps de l'erreur est un tableau JSON.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing selector": {
                    "value": [
                      "Provide vendor_data_list, didit_internal_id_list, or set delete_all=true."
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas supprimer d'entreprises pour cette application. Une clé manquante renvoie `403` ; une clé incorrecte, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Rien n'est supprimé. `code` en indique la raison : `in_filed_report` lorsque la sélection inclut une entreprise présente dans un rapport réglementaire finalisé, `subject_deletion_in_progress` lorsqu'une autre requête est encore en train de supprimer l'une des entreprises sélectionnées. Réessayez la requête une fois cette suppression terminée.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/InFiledReportError"
                    },
                    {
                      "$ref": "#/components/schemas/SubjectDeletionInProgressError"
                    }
                  ]
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/users/aml-monitoring/": {
      "post": {
        "summary": "Activer ou désactiver la surveillance AML continue pour les utilisateurs",
        "description": "Active ou désactive la surveillance AML continue pour les utilisateurs sélectionnés, avec la même sémantique que la Business Console. Exactement un filtrage AML surveillé est conservé par utilisateur, ainsi un profil vérifié plusieurs fois est surveillé et facturé une seule fois ; la désactivation coupe la surveillance sur tous les filtrages du profil. Les utilisateurs sans aucun filtrage AML sont d'abord analysés (facturés comme un filtrage AML standard) lorsqu'ils disposent du nom complet, de la date de naissance et du pays nécessaires ; sinon, ils sont signalés comme `skipped_no_identity_data`.\n\nDéfinissez `estimate_only: true` pour prévisualiser les volumes et les coûts sans rien écrire. Les sélections de 20 profils ou moins sont traitées immédiatement et renvoient `200` avec la tâche terminée ; les sélections plus importantes renvoient `202` et s'exécutent en arrière-plan - interrogez [Get AML monitoring job](#get-/v3/aml-monitoring/jobs/-job_id-/) avec le `job_id` renvoyé. L'activation est refusée avec `403` lorsque le solde de l'organisation ne couvre pas l'estimation. Les identifiants qui ne correspondent à rien sont listés dans `unmatched` et ne font jamais échouer la requête : une sélection sans correspondance se termine comme une tâche vide (`total` égal à 0), selon la même convention que les endpoints de suppression par lot.",
        "operationId": "toggle_users_aml_monitoring",
        "x-didit-sdk": {
          "resource": "users",
          "method": "set_aml_monitoring",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "AML Ongoing Monitoring"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "is_enabled"
                ],
                "description": "Sélectionnez des utilisateurs avec `vendor_data_list`, `didit_internal_id_list`, ou les deux (les deux listes sont combinées avec un opérateur OU). Au maximum 1000 identifiants par requête sur l'ensemble des deux listes.",
                "properties": {
                  "is_enabled": {
                    "type": "boolean",
                    "description": "true pour activer la surveillance, false pour la désactiver."
                  },
                  "estimate_only": {
                    "type": "boolean",
                    "default": false,
                    "description": "Si true, renvoie l'estimation des coûts et n'effectue aucune écriture : aucun filtrage, aucune facturation, aucune tâche."
                  },
                  "vendor_data_list": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Vos propres identifiants des utilisateurs à basculer, mis en correspondance exacte avec ceux transmis."
                  },
                  "didit_internal_id_list": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "Identifiants internes Didit des utilisateurs à basculer - le `didit_internal_id` renvoyé par les endpoints de création, d'obtention et de liste."
                  }
                }
              },
              "examples": {
                "Estimate first": {
                  "summary": "Prévisualiser le coût sans écriture",
                  "value": {
                    "is_enabled": true,
                    "estimate_only": true,
                    "vendor_data_list": [
                      "user-123",
                      "user-456"
                    ]
                  }
                },
                "Enable": {
                  "summary": "Activer la surveillance pour deux utilisateurs",
                  "value": {
                    "is_enabled": true,
                    "vendor_data_list": [
                      "user-123",
                      "user-456"
                    ]
                  }
                },
                "Disable": {
                  "summary": "Désactiver la surveillance par l'identifiant interne Didit",
                  "value": {
                    "is_enabled": false,
                    "didit_internal_id_list": [
                      "3f1c0d3e-8f0a-4c2e-9a3d-9b1f5f4a2c11"
                    ]
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/users/aml-monitoring/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"is_enabled\": true, \"vendor_data_list\": [\"user-123\", \"user-456\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.users.set_aml_monitoring(\n    is_enabled=True,\n    estimate_only=True,\n    vendor_data_list=[\"user-123\", \"user-456\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.users.setAmlMonitoring({\n  is_enabled: true,\n  estimate_only: true,\n  vendor_data_list: [\"user-123\", \"user-456\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Users.SetAMLMonitoring(ctx, didit.UsersSetAMLMonitoringParams{\n\tIsEnabled:      true,\n\tEstimateOnly:   didit.Bool(true),\n\tVendorDataList: didit.Some([]string{\"user-123\", \"user-456\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.UsersSetAmlMonitoringParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.users().setAmlMonitoring(UsersSetAmlMonitoringParams.builder()\n        .isEnabled(true)\n        .estimateOnly(true)\n        .vendorDataList(List.of(\"user-123\", \"user-456\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->users->setAmlMonitoring([\n    'is_enabled' => true,\n    'estimate_only' => true,\n    'vendor_data_list' => ['user-123', 'user-456'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.users.set_aml_monitoring(\n  is_enabled: true,\n  estimate_only: true,\n  vendor_data_list: [\"user-123\", \"user-456\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Users.SetAmlMonitoringAsync(new UsersSetAmlMonitoringParams\n{\n    IsEnabled = true,\n    EstimateOnly = true,\n    VendorDataList = new string[] { \"user-123\", \"user-456\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'estimation (lorsque `estimate_only` est true) ou la tâche terminée pour une sélection traitée en ligne.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AMLMonitoringToggleResult"
                }
              }
            }
          },
          "202": {
            "description": "Les sélections plus volumineuses s'exécutent en arrière-plan. Interrogez l'endpoint du job avec `job_id` ; `results` se remplit au fur et à mesure du traitement des profils.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AMLMonitoringJob"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation : `is_enabled` manquant, aucun sélecteur, ou plus de 1000 identifiants sur l'ensemble des deux listes."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "Solde insuffisant pour activer la surveillance pour cette sélection. La réponse contient l'`estimate` afin que vous puissiez recharger le montant approprié.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "estimate": {
                      "type": "object",
                      "description": "Aperçu du coût. Renvoyé directement lorsque estimate_only est vrai (rien n'est écrit).",
                      "properties": {
                        "users_total": {
                          "type": "integer",
                          "description": "Profils correspondant à la sélection."
                        },
                        "already_enabled": {
                          "type": "integer",
                          "description": "Profils déjà surveillés (aucune action lors de l'activation ; ce sont ceux que la désactivation désactive)."
                        },
                        "with_existing_aml": {
                          "type": "integer",
                          "description": "Profils dont le filtrage AML existant passera en mode surveillé (aucun nouveau filtrage)."
                        },
                        "needing_screening": {
                          "type": "integer",
                          "description": "Profils sans aucun filtrage AML qui seront d'abord filtrés (facturés comme un filtrage AML standard)."
                        },
                        "skipped_no_identity_data": {
                          "type": "integer",
                          "description": "Profils ne pouvant pas faire l'objet d'un filtrage en raison de données d'identité manquantes."
                        },
                        "skipped_blocked": {
                          "type": "integer",
                          "description": "Utilisateurs bloqués qui seront ignorés (toujours 0 pour les entreprises)."
                        },
                        "estimated_screening_cost_usd": {
                          "type": "number",
                          "example": 0.2,
                          "description": "Coût ponctuel des nouveaux filtrages."
                        },
                        "estimated_annual_monitoring_cost_usd": {
                          "type": "number",
                          "example": 0.07,
                          "description": "Coût de surveillance annuel des profils qui deviendront surveillés."
                        },
                        "balance_sufficient": {
                          "type": "boolean",
                          "description": "Indique si le solde de l'organisation couvre le filtrage ainsi que la première année de surveillance."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/businesses/aml-monitoring/": {
      "post": {
        "summary": "Activer ou désactiver la surveillance AML continue pour les entreprises",
        "description": "Active ou désactive la surveillance AML continue pour les entreprises sélectionnées, avec la même sémantique que la Business Console. Exactement un filtrage AML surveillé est conservé par entreprise, ainsi un profil vérifié plusieurs fois est surveillé et facturé une seule fois ; la désactivation coupe la surveillance sur tous les filtrages du profil. Les entreprises sans aucun filtrage AML sont d'abord analysées (facturées comme un filtrage AML standard) lorsqu'elles disposent de la raison sociale ou du nom d'affichage nécessaire ; sinon, elles sont signalées comme `skipped_no_identity_data`.\n\nDéfinissez `estimate_only: true` pour prévisualiser les volumes et les coûts sans rien écrire. Les sélections de 20 profils ou moins sont traitées immédiatement et renvoient `200` avec la tâche terminée ; les sélections plus importantes renvoient `202` et s'exécutent en arrière-plan - interrogez [Get AML monitoring job](#get-/v3/aml-monitoring/jobs/-job_id-/) avec le `job_id` renvoyé. L'activation est refusée avec `403` lorsque le solde de l'organisation ne couvre pas l'estimation. Les identifiants qui ne correspondent à rien sont listés dans `unmatched` et ne font jamais échouer la requête : une sélection sans correspondance se termine comme une tâche vide (`total` égal à 0), selon la même convention que les endpoints de suppression par lot.",
        "operationId": "toggle_businesses_aml_monitoring",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "set_aml_monitoring",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "AML Ongoing Monitoring"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "is_enabled"
                ],
                "description": "Sélectionnez des entreprises avec `vendor_data_list`, `didit_internal_id_list`, ou les deux (les deux listes sont combinées avec un opérateur OU). Au maximum 1000 identifiants par requête sur l'ensemble des deux listes.",
                "properties": {
                  "is_enabled": {
                    "type": "boolean",
                    "description": "true pour activer la surveillance, false pour la désactiver."
                  },
                  "estimate_only": {
                    "type": "boolean",
                    "default": false,
                    "description": "Si true, renvoie l'estimation des coûts et n'effectue aucune écriture : aucun filtrage, aucune facturation, aucune tâche."
                  },
                  "vendor_data_list": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Vos propres identifiants des entreprises à basculer, mis en correspondance exacte avec ceux transmis."
                  },
                  "didit_internal_id_list": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "Identifiants internes Didit des entreprises à basculer - le `didit_internal_id` renvoyé par les endpoints de création, de récupération et de liste."
                  }
                }
              },
              "examples": {
                "Estimate first": {
                  "summary": "Prévisualiser le coût sans écriture",
                  "value": {
                    "is_enabled": true,
                    "estimate_only": true,
                    "vendor_data_list": [
                      "company-123",
                      "company-456"
                    ]
                  }
                },
                "Enable": {
                  "summary": "Activer la surveillance pour deux entreprises",
                  "value": {
                    "is_enabled": true,
                    "vendor_data_list": [
                      "company-123",
                      "company-456"
                    ]
                  }
                },
                "Disable": {
                  "summary": "Désactiver la surveillance par l'identifiant interne Didit",
                  "value": {
                    "is_enabled": false,
                    "didit_internal_id_list": [
                      "3f1c0d3e-8f0a-4c2e-9a3d-9b1f5f4a2c11"
                    ]
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/businesses/aml-monitoring/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"is_enabled\": true, \"vendor_data_list\": [\"company-123\", \"company-456\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.businesses.set_aml_monitoring(\n    is_enabled=True,\n    estimate_only=True,\n    vendor_data_list=[\"company-123\", \"company-456\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.businesses.setAmlMonitoring({\n  is_enabled: true,\n  estimate_only: true,\n  vendor_data_list: [\"company-123\", \"company-456\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.SetAMLMonitoring(ctx, didit.BusinessesSetAMLMonitoringParams{\n\tIsEnabled:      true,\n\tEstimateOnly:   didit.Bool(true),\n\tVendorDataList: didit.Some([]string{\"company-123\", \"company-456\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.BusinessesSetAmlMonitoringParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.businesses().setAmlMonitoring(BusinessesSetAmlMonitoringParams.builder()\n        .isEnabled(true)\n        .estimateOnly(true)\n        .vendorDataList(List.of(\"company-123\", \"company-456\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->businesses->setAmlMonitoring([\n    'is_enabled' => true,\n    'estimate_only' => true,\n    'vendor_data_list' => ['company-123', 'company-456'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.businesses.set_aml_monitoring(\n  is_enabled: true,\n  estimate_only: true,\n  vendor_data_list: [\"company-123\", \"company-456\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.SetAmlMonitoringAsync(new BusinessesSetAmlMonitoringParams\n{\n    IsEnabled = true,\n    EstimateOnly = true,\n    VendorDataList = new string[] { \"company-123\", \"company-456\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'estimation (lorsque `estimate_only` est true) ou la tâche terminée pour une sélection traitée en ligne.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AMLMonitoringToggleResult"
                }
              }
            }
          },
          "202": {
            "description": "Les sélections plus volumineuses s'exécutent en arrière-plan. Interrogez l'endpoint du job avec `job_id` ; `results` se remplit au fur et à mesure du traitement des profils.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AMLMonitoringJob"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation : `is_enabled` manquant, aucun sélecteur, ou plus de 1000 identifiants sur l'ensemble des deux listes."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "Solde insuffisant pour activer la surveillance pour cette sélection. La réponse contient l'`estimate` afin que vous puissiez recharger le montant approprié.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "estimate": {
                      "type": "object",
                      "description": "Aperçu du coût. Renvoyé directement lorsque estimate_only est vrai (rien n'est écrit).",
                      "properties": {
                        "users_total": {
                          "type": "integer",
                          "description": "Profils correspondant à la sélection."
                        },
                        "already_enabled": {
                          "type": "integer",
                          "description": "Profils déjà surveillés (aucune action lors de l'activation ; ce sont ceux que la désactivation désactive)."
                        },
                        "with_existing_aml": {
                          "type": "integer",
                          "description": "Profils dont le filtrage AML existant passera en mode surveillé (aucun nouveau filtrage)."
                        },
                        "needing_screening": {
                          "type": "integer",
                          "description": "Profils sans aucun filtrage AML qui seront d'abord filtrés (facturés comme un filtrage AML standard)."
                        },
                        "skipped_no_identity_data": {
                          "type": "integer",
                          "description": "Profils ne pouvant pas faire l'objet d'un filtrage en raison de données d'identité manquantes."
                        },
                        "skipped_blocked": {
                          "type": "integer",
                          "description": "Utilisateurs bloqués qui seront ignorés (toujours 0 pour les entreprises)."
                        },
                        "estimated_screening_cost_usd": {
                          "type": "number",
                          "example": 0.2,
                          "description": "Coût ponctuel des nouveaux filtrages."
                        },
                        "estimated_annual_monitoring_cost_usd": {
                          "type": "number",
                          "example": 0.07,
                          "description": "Coût de surveillance annuel des profils qui deviendront surveillés."
                        },
                        "balance_sufficient": {
                          "type": "boolean",
                          "description": "Indique si le solde de l'organisation couvre le filtrage ainsi que la première année de surveillance."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/aml-monitoring/jobs/{job_id}/": {
      "get": {
        "summary": "Obtenir une tâche de surveillance AML continue",
        "description": "Statut, compteurs de résultats et résultats par enregistrement d'une tâche de basculement de surveillance initiée depuis `POST /v3/users/aml-monitoring/` ou `POST /v3/businesses/aml-monitoring/`. Interrogez toutes les deux secondes tant que `status` est à `PENDING` ou `PROCESSING` ; `results` est complet dès qu'il passe à `COMPLETED`.",
        "operationId": "get_aml_monitoring_job",
        "x-didit-sdk": {
          "resource": "aml_monitoring",
          "method": "retrieve_job",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "AML Ongoing Monitoring"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Le `job_id` renvoyé par l'endpoint de basculement."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl 'https://verification.didit.me/v3/aml-monitoring/jobs/JOB_ID/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.aml_monitoring.retrieve_job(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.amlMonitoring.retrieveJob(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.AMLMonitoring.RetrieveJob(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.amlMonitoring().retrieveJob(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->amlMonitoring->retrieveJob('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.aml_monitoring.retrieve_job(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.AmlMonitoring.RetrieveJobAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La tâche.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "PENDING",
                        "PROCESSING",
                        "COMPLETED",
                        "FAILED"
                      ]
                    },
                    "is_enabled": {
                      "type": "boolean",
                      "description": "true lorsque le traitement active la surveillance, false lorsqu'il la désactive."
                    },
                    "target_type": {
                      "type": "string",
                      "enum": [
                        "user",
                        "business"
                      ],
                      "description": "Quelle famille de profils la tâche active ou désactive."
                    },
                    "total": {
                      "type": "integer",
                      "description": "Profils traités par la tâche."
                    },
                    "processed": {
                      "type": "integer",
                      "description": "Profils traités jusqu'à présent."
                    },
                    "outcomes": {
                      "type": "object",
                      "description": "Compteurs de résultats par enregistrement. Chaque profil sélectionné est associé à exactement un compteur ; rien n'est ignoré silencieusement.",
                      "properties": {
                        "enabled": {
                          "type": "integer",
                          "description": "Surveillance activée sur un filtrage AML existant."
                        },
                        "screened_and_enabled": {
                          "type": "integer",
                          "description": "Un nouveau filtrage AML a été créé (facturé) et la surveillance y a été activée."
                        },
                        "already_enabled": {
                          "type": "integer",
                          "description": "La surveillance était déjà active ; rien n'a changé et rien n'a été facturé."
                        },
                        "disabled": {
                          "type": "integer",
                          "description": "Surveillance désactivée sur l'ensemble des filtrages AML du profil."
                        },
                        "skipped_no_identity_data": {
                          "type": "integer",
                          "description": "Ignoré : le profil ne contient pas le nom complet, la date de naissance et le pays (utilisateurs) ou un nom (entreprises) nécessaires pour le filtrage."
                        },
                        "skipped_blocked": {
                          "type": "integer",
                          "description": "Ignoré : l'utilisateur est bloqué."
                        },
                        "skipped_sandbox": {
                          "type": "integer",
                          "description": "Ignoré : application en sandbox, aucun filtrage n'est créé."
                        },
                        "failed_provider": {
                          "type": "integer",
                          "description": "Le filtrage n'a pas pu être effectué ; réessayez plus tard."
                        },
                        "failed_insufficient_balance": {
                          "type": "integer",
                          "description": "Le solde a été épuisé pendant l'exécution de la tâche."
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "description": "Une entrée par profil traité, dans l'ordre de traitement. La liste s'allonge pendant l'exécution de la tâche ; complète une fois que le statut est COMPLETED. Enregistré pour les tâches démarrées via l'API ; une tâche démarrée depuis la Business Console ne renvoie que des compteurs.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "didit_internal_id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Identifiant interne Didit du profil."
                          },
                          "vendor_data": {
                            "type": "string",
                            "nullable": true,
                            "description": "Votre propre identifiant pour le profil."
                          },
                          "outcome": {
                            "type": "string",
                            "enum": [
                              "enabled",
                              "screened_and_enabled",
                              "already_enabled",
                              "disabled",
                              "skipped_no_identity_data",
                              "skipped_blocked",
                              "skipped_sandbox",
                              "failed_provider",
                              "failed_insufficient_balance"
                            ]
                          }
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "nullable": true,
                      "description": "Message d'échec générique lorsque le statut est FAILED ; la cause détaillée est conservée côté plateforme."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "completed_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "404": {
            "description": "Aucune tâche de ce type pour cette application."
          }
        }
      }
    },
    "/v3/users/{vendor_data}/update-status/": {
      "patch": {
        "summary": "Mettre à jour le statut de l'utilisateur",
        "description": "Basculer uniquement le `status` de cycle de vie d'un utilisateur : `ACTIVE`, `FLAGGED` ou `BLOCKED` (pas les statuts de session). `BLOCKED` ajoute le `vendor_data` à la liste de blocage du système ; quitter l'état `BLOCKED` supprime cette entrée. Chaque modification est enregistrée sous forme d'activité `STATUS_CHANGED` sur l'utilisateur, avec le `reason` facultatif comme `comment`. Envoyer le statut actuel ne change rien et n'enregistre aucun `reason`. Le webhook `user.status.updated` ne transmet pas `reason`.",
        "operationId": "update_user_status",
        "x-didit-sdk": {
          "resource": "users",
          "method": "update_status",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "vendor_data",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Votre identifiant unique pour l'utilisateur."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EntityStatusUpdateRequest"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 1000,
                        "description": "Raison pour laquelle le statut a changé. Enregistrée sur l'entrée de changement de statut de l'activité de l'utilisateur (`comments[].comment`, et **Activité** dans la Business Console), uniquement lorsque le statut change réellement. Les webhooks ne la transmettent pas."
                      }
                    }
                  }
                ]
              },
              "examples": {
                "Activate": {
                  "summary": "Réactiver l'utilisateur",
                  "value": {
                    "status": "ACTIVE"
                  }
                },
                "Flag": {
                  "summary": "Signaler l'utilisateur pour examen",
                  "value": {
                    "status": "FLAGGED"
                  }
                },
                "Block": {
                  "summary": "Bloquer l'utilisateur (ajoute à la liste de blocage du système)",
                  "value": {
                    "status": "BLOCKED"
                  }
                },
                "Block with reason": {
                  "summary": "Bloquer l'utilisateur et consigner le motif",
                  "value": {
                    "status": "BLOCKED",
                    "reason": "Chargeback fraud pattern confirmed"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/users/user-abc-123/update-status/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"status\": \"BLOCKED\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.users.update_status(\n    \"user-123\",\n    status=\"ACTIVE\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.users.updateStatus(\"user-123\", {\n  status: \"ACTIVE\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Users.UpdateStatus(ctx, \"user-123\", didit.UsersUpdateStatusParams{\n\tStatus: \"ACTIVE\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.EntityStatusUpdateRequest;\nimport me.didit.types.UsersUpdateStatusParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.users().updateStatus(\"user-123\", UsersUpdateStatusParams.builder()\n        .status(EntityStatusUpdateRequest.Status.of(\"ACTIVE\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->users->updateStatus('user-123', [\n    'status' => 'ACTIVE',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.users.update_status(\n  \"user-123\",\n  status: \"ACTIVE\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Users.UpdateStatusAsync(\"user-123\", new UsersUpdateStatusParams\n{\n    Status = \"ACTIVE\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Statut de l'utilisateur mis à jour. Enregistrement utilisateur complet renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDetailItem"
                },
                "examples": {
                  "Blocked": {
                    "value": {
                      "didit_internal_id": "f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418",
                      "vendor_data": "user-abc-123",
                      "display_name": null,
                      "full_name": "John Michael Doe",
                      "date_of_birth": "1990-05-15",
                      "effective_name": "John Michael Doe",
                      "status": "BLOCKED",
                      "metadata": {
                        "tier": "premium",
                        "source": "website"
                      },
                      "portrait_image_url": "https://<media-host>/...",
                      "session_count": 3,
                      "approved_count": 2,
                      "declined_count": 0,
                      "in_review_count": 1,
                      "issuing_states": [
                        "USA"
                      ],
                      "approved_emails": [
                        "john@example.com"
                      ],
                      "approved_phones": [
                        "+14155551234"
                      ],
                      "features": {
                        "ID_VERIFICATION": "Approved",
                        "LIVENESS": "Approved",
                        "FACE_MATCH": "Approved",
                        "AML": "Approved"
                      },
                      "features_list": [
                        {
                          "feature": "ID_VERIFICATION",
                          "status": "Approved"
                        },
                        {
                          "feature": "LIVENESS",
                          "status": "Approved"
                        },
                        {
                          "feature": "FACE_MATCH",
                          "status": "Approved"
                        },
                        {
                          "feature": "AML",
                          "status": "Approved"
                        }
                      ],
                      "last_session_at": "2025-06-15T10:30:00Z",
                      "last_activity_at": "2025-06-15T10:30:00Z",
                      "first_session_at": "2025-06-01T08:00:00Z",
                      "tags": [
                        {
                          "uuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
                          "tag": {
                            "uuid": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
                            "name": "VIP",
                            "color": "#2567FF",
                            "description": null,
                            "source": "custom",
                            "created_at": "2025-05-01T09:00:00Z",
                            "updated_at": "2025-05-01T09:00:00Z"
                          },
                          "added_by_email": "analyst@acme.com",
                          "added_by_name": "Jane Analyst",
                          "created_at": "2025-06-02T11:00:00Z"
                        }
                      ],
                      "comments": [
                        {
                          "uuid": "c1111111-2222-4333-8444-555555555555",
                          "comment_type": "STATUS_CHANGED",
                          "comment": "Chargeback fraud pattern confirmed",
                          "actor_email": null,
                          "actor_name": null,
                          "previous_status": "ACTIVE",
                          "new_status": "BLOCKED",
                          "previous_value": null,
                          "new_value": null,
                          "changed_fields": [],
                          "metadata": null,
                          "mentioned_emails": [],
                          "created_at": "2025-06-15T10:30:00Z"
                        }
                      ],
                      "created_at": "2025-06-01T08:00:00Z",
                      "updated_at": "2025-06-15T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`status` manquant ou invalide, ou un `reason` de plus de 1000 caractères.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing status": {
                    "value": {
                      "status": [
                        "This field is required."
                      ]
                    }
                  },
                  "Bad status": {
                    "value": {
                      "status": [
                        "Invalid status. Valid options are: ACTIVE, FLAGGED, BLOCKED"
                      ]
                    }
                  },
                  "Reason too long": {
                    "value": {
                      "reason": [
                        "Ensure this field has no more than 1000 characters."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Aucun identifiant fourni. Les requêtes vers les chemins `/v3/users/*` sans en-tête `x-api-key` (ou token `Authorization: Bearer`) sont rejetées par le middleware d'authentification avant d'atteindre l'API.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing credentials": {
                    "value": {
                      "detail": "You must be authenticated with a valid access token to access this endpoint."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé ne peut pas mettre à jour les utilisateurs pour cette application. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun utilisateur (non supprimé) avec le `vendor_data` fourni n'existe pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/businesses/create/": {
      "post": {
        "summary": "Créer une entreprise",
        "description": "Pré-créez une [entreprise](/entities/businesses) *sans* session KYB. Tous les champs sont facultatifs, mais vous devez toujours envoyer `vendor_data` — sans cela, l'enregistrement ne peut pas être lié à des sessions ou des transactions. Lorsqu'il est fourni, `vendor_data` doit être unique parmi les entreprises non supprimées (correspondance exacte ; les conflits renvoient une erreur 400). Non idempotent.",
        "operationId": "create_business",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Businesses"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "vendor_data": {
                    "type": "string",
                    "nullable": true,
                    "description": "Votre identifiant unique pour cette entreprise (chaîne libre, PAS un UUID). Facultatif mais fortement recommandé. Lorsqu'il est fourni, il doit être unique parmi les entreprises non supprimées de l'application ; mis en correspondance exactement tel qu'envoyé."
                  },
                  "display_name": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 255,
                    "description": "Nom d'affichage convivial affiché dans la console (prend le pas sur `legal_name` pour l'affichage de l'interface utilisateur)."
                  },
                  "legal_name": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 255,
                    "description": "Raison sociale officielle de l'entreprise."
                  },
                  "registration_number": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 100,
                    "description": "Numéro d'immatriculation ou de constitution de l'entreprise."
                  },
                  "country_code": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 10,
                    "description": "Pays de constitution (ISO 3166-1 alpha-2, par ex. `GB`, `US`)."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "ACTIVE",
                      "FLAGGED",
                      "BLOCKED"
                    ],
                    "default": "ACTIVE",
                    "description": "Statut de cycle de vie initial. La valeur par défaut est `ACTIVE`."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "Objet JSON arbitraire que vous associez à l'entreprise. La valeur par défaut est `{}`."
                  }
                }
              },
              "examples": {
                "Basic": {
                  "summary": "Minimum recommandé",
                  "value": {
                    "vendor_data": "company-456",
                    "legal_name": "New Corp Ltd",
                    "country_code": "US"
                  }
                },
                "Full": {
                  "summary": "Tous les champs",
                  "value": {
                    "vendor_data": "company-789",
                    "display_name": "New Corp",
                    "legal_name": "New Corp International Ltd",
                    "registration_number": "98765432",
                    "country_code": "DE",
                    "status": "ACTIVE",
                    "metadata": {
                      "industry": "fintech",
                      "tier": "enterprise"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/businesses/create/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"vendor_data\": \"company-456\", \"legal_name\": \"New Corp Ltd\", \"country_code\": \"US\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.businesses.create(\n    vendor_data=\"company-456\",\n    legal_name=\"New Corp Ltd\",\n    country_code=\"US\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.businesses.create({\n  vendor_data: \"company-456\",\n  legal_name: \"New Corp Ltd\",\n  country_code: \"US\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.Create(ctx, didit.BusinessesCreateParams{\n\tVendorData:  didit.String(\"company-456\"),\n\tLegalName:   didit.String(\"New Corp Ltd\"),\n\tCountryCode: didit.String(\"US\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.BusinessesCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.businesses().create(BusinessesCreateParams.builder()\n        .vendorData(\"company-456\")\n        .legalName(\"New Corp Ltd\")\n        .countryCode(\"US\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->businesses->create([\n    'vendor_data' => 'company-456',\n    'legal_name' => 'New Corp Ltd',\n    'country_code' => 'US',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.businesses.create(\n  vendor_data: \"company-456\",\n  legal_name: \"New Corp Ltd\",\n  country_code: \"US\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.CreateAsync(new BusinessesCreateParams\n{\n    VendorData = \"company-456\",\n    LegalName = \"New Corp Ltd\",\n    CountryCode = \"US\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Entreprise créée. L'enregistrement complet de l'entreprise est renvoyé (même format que Get Business).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessDetailItem"
                },
                "examples": {
                  "Created": {
                    "value": {
                      "didit_internal_id": "a1b2c3d4-e5f6-4890-abcd-ef1234567890",
                      "vendor_data": "company-456",
                      "display_name": null,
                      "legal_name": "New Corp Ltd",
                      "registration_number": null,
                      "country_code": "US",
                      "effective_name": "New Corp Ltd",
                      "status": "ACTIVE",
                      "session_count": 0,
                      "approved_count": 0,
                      "declined_count": 0,
                      "in_review_count": 0,
                      "features": {},
                      "features_list": [],
                      "last_session_at": null,
                      "last_activity_at": "2026-03-15T10:30:00Z",
                      "first_session_at": null,
                      "tags": [],
                      "created_at": "2026-03-15T10:30:00Z",
                      "metadata": {},
                      "updated_at": "2026-03-15T10:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide — généralement un `vendor_data` en double, un `status` inconnu ou des `metadata` malformées.",
            "content": {
              "application/json": {
                "examples": {
                  "Duplicate": {
                    "value": {
                      "vendor_data": [
                        "A business with this vendor_data already exists."
                      ]
                    }
                  },
                  "Bad status": {
                    "value": {
                      "status": [
                        "Invalid status. Valid options are: ACTIVE, FLAGGED, BLOCKED"
                      ]
                    }
                  },
                  "Bad metadata": {
                    "value": {
                      "metadata": [
                        "Metadata must be a JSON object."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou la clé ne peut pas créer d'entreprises pour cette application. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/users/create/": {
      "post": {
        "summary": "Créer un utilisateur",
        "description": "Créez un [utilisateur](/entities/users) à l'aide de `vendor_data`, avant ou sans session de vérification. `vendor_data` doit être unique parmi les utilisateurs de l'application (un doublon renvoie `400`). Non idempotent.\n\n**Coordonnées :** `email` et `phone_number` sont stockés dans `metadata.contact`, et `country` dans `metadata.address`. Lorsque vous envoyez `first_name` ou `last_name` sans `full_name`, Didit les combine dans `full_name`.\n\n**Lien de vérification :** avec `send_verification_link: true`, Didit crée également une session de vérification pour la personne sur `workflow_id` et lui envoie le lien par e-mail à `email`. La session exécute les mêmes vérifications que [Créer une session](/fr/sessions-api/create-session), telles que la liste de blocage et votre solde de crédits. La personne et la session sont créées ensemble ou pas du tout : si une vérification échoue, rien n'est écrit et aucun e-mail n'est envoyé. Le champ `verification_link` de la réponse décrit la session, et vaut `null` lorsque vous ne demandez pas de lien.\n\n**Accès par clé API :** une clé API restreinte nécessite les droits d'écriture sur `users`. Avec `send_verification_link: true`, elle nécessite également les droits d'écriture sur `sessions`, sinon l'appel renvoie `403` avant que quoi que ce soit ne soit écrit. Les clés à accès complet ne sont pas affectées. Consultez [Clés API](/fr/console/api-keys).",
        "operationId": "create_user",
        "x-didit-sdk": {
          "resource": "users",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Users"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "vendor_data"
                ],
                "properties": {
                  "vendor_data": {
                    "type": "string",
                    "description": "Votre identifiant unique pour cet utilisateur (chaîne libre, PAS un UUID). Doit être unique parmi les utilisateurs de l'application ; mis en correspondance exactement tel qu'envoyé."
                  },
                  "full_name": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 512,
                    "description": "Nom complet légal de l'utilisateur."
                  },
                  "display_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "Nom d'affichage convivial affiché dans la console (prend le pas sur `full_name` pour l'affichage de l'interface utilisateur).",
                    "maxLength": 255
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Date de naissance au format `YYYY-MM-DD`."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "ACTIVE",
                      "FLAGGED",
                      "BLOCKED"
                    ],
                    "default": "ACTIVE",
                    "description": "Statut de cycle de vie initial. La valeur par défaut est `ACTIVE`."
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "Objet JSON arbitraire que vous associez à l'utilisateur. La valeur par défaut est `{}`."
                  },
                  "approved_emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Adresses e-mail pré-approuvées pour cet utilisateur, par exemple `[\"john@example.com\"]`."
                  },
                  "approved_phones": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Numéros de téléphone pré-approuvés pour cet utilisateur, par exemple `[\"+14155551234\"]`."
                  },
                  "issuing_states": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Pays de délivrance pré-enregistrés (ISO 3166-1 alpha-3), par exemple `[\"USA\"]`."
                  },
                  "first_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Prénom. Lorsque `full_name` n'est pas envoyé, Didit concatène `first_name` et `last_name` avec un espace pour former `full_name`. Non renvoyé sous la forme d'un champ distinct."
                  },
                  "last_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom de famille. Combiné avec `first_name` pour former `full_name` lorsque `full_name` n'est pas envoyé. N'est pas renvoyé en tant que champ distinct."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "E-mail de contact, stocké dans `metadata.contact.email` (il remplace un `email` que vous envoyez dans `metadata.contact`). Requis lorsque `send_verification_link` est défini sur `true` : le lien est envoyé à cette adresse. Si `metadata.contact` n'est pas un objet JSON, l'appel renvoie `400` sur ce champ."
                  },
                  "phone_number": {
                    "type": "string",
                    "maxLength": 32,
                    "description": "Numéro de téléphone de contact, stocké dans `metadata.contact.phone_number`. Si `metadata.contact` n'est pas un objet JSON, l'appel renvoie `400` sur ce champ."
                  },
                  "country": {
                    "type": "string",
                    "maxLength": 3,
                    "description": "Pays sous forme de code ISO 3166, alpha-2 ou alpha-3 (`ES` ou `ESP`). Stocké en majuscules dans `metadata.address.country`. Si `metadata.address` n'est pas un objet JSON, l'appel renvoie `400` sur ce champ."
                  },
                  "send_verification_link": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lorsque la valeur est `true`, Didit crée une session de vérification pour la personne sur le workflow `workflow_id` et lui envoie le lien par e-mail à l'adresse `email`. Nécessite `email` et `workflow_id`. Une clé API restreinte nécessite également les droits d'écriture sur `sessions`."
                  },
                  "workflow_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Le workflow de la session de vérification. Requis lorsque `send_verification_link` vaut `true`. Il doit vérifier une personne : un workflow de Vérification d'entreprise (KYB) est refusé. Ignoré dans le cas contraire."
                  },
                  "language": {
                    "type": "string",
                    "maxLength": 10,
                    "description": "Langue de l'e-mail de vérification, sous forme de code de [langue prise en charge](/fr/integration/supported-languages). Anglais en cas d'omission. Ignoré lorsque `send_verification_link` n'est pas `true`."
                  }
                }
              },
              "examples": {
                "Basic": {
                  "summary": "Créer avec les informations de base",
                  "value": {
                    "vendor_data": "user-abc-123",
                    "full_name": "John Doe"
                  }
                },
                "Full": {
                  "summary": "Tous les champs",
                  "value": {
                    "vendor_data": "user-abc-456",
                    "full_name": "Jane Smith",
                    "display_name": "Jane S.",
                    "date_of_birth": "1990-05-15",
                    "status": "ACTIVE",
                    "metadata": {
                      "tier": "premium",
                      "source": "api"
                    },
                    "approved_emails": [
                      "jane@example.com"
                    ]
                  }
                },
                "Contact details": {
                  "summary": "Nom, e-mail, téléphone et pays",
                  "value": {
                    "vendor_data": "user-abc-789",
                    "first_name": "Julia",
                    "last_name": "Martin",
                    "email": "julia.martin@example.com",
                    "phone_number": "+34600000000",
                    "country": "ES"
                  }
                },
                "With verification link": {
                  "summary": "Créer la personne et lui envoyer un lien de vérification par e-mail",
                  "value": {
                    "vendor_data": "user-abc-789",
                    "first_name": "Julia",
                    "last_name": "Martin",
                    "email": "julia.martin@example.com",
                    "send_verification_link": true,
                    "workflow_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "language": "es"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/users/create/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"vendor_data\": \"user-abc-123\", \"full_name\": \"John Doe\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.users.create(\n    vendor_data=\"user-abc-123\",\n    full_name=\"John Doe\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.users.create({\n  vendor_data: \"user-abc-123\",\n  full_name: \"John Doe\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Users.Create(ctx, didit.UsersCreateParams{\n\tVendorData: \"user-abc-123\",\n\tFullName:   didit.String(\"John Doe\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.UsersCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.users().create(UsersCreateParams.builder()\n        .vendorData(\"user-abc-123\")\n        .fullName(\"John Doe\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->users->create([\n    'vendor_data' => 'user-abc-123',\n    'full_name' => 'John Doe',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.users.create(\n  vendor_data: \"user-abc-123\",\n  full_name: \"John Doe\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Users.CreateAsync(new UsersCreateParams\n{\n    VendorData = \"user-abc-123\",\n    FullName = \"John Doe\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Utilisateur créé. Enregistrement utilisateur complet (même format que Obtenir un utilisateur), plus `verification_link` : la session de vérification envoyée par e-mail par Didit lorsque `send_verification_link` était à `true`, sinon `null`.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/UserDetailItem"
                    },
                    {
                      "type": "object",
                      "required": [
                        "verification_link"
                      ],
                      "properties": {
                        "verification_link": {
                          "type": "object",
                          "nullable": true,
                          "description": "La session de vérification créée et envoyée par e-mail à la personne par Didit. Toujours présent : `null` lorsque `send_verification_link` n'était pas `true`.",
                          "required": [
                            "session_id",
                            "session_number",
                            "status",
                            "url",
                            "workflow_id",
                            "email"
                          ],
                          "properties": {
                            "session_id": {
                              "type": "string",
                              "format": "uuid",
                              "description": "Identifiant de la session de vérification."
                            },
                            "session_number": {
                              "type": "integer",
                              "description": "Numéro séquentiel de la session au sein de votre application."
                            },
                            "status": {
                              "type": "string",
                              "description": "Statut de la session, `Not Started` pour une session qui vient d'être créée."
                            },
                            "url": {
                              "type": "string",
                              "format": "uri",
                              "description": "Le lien de vérification envoyé par e-mail à la personne par Didit."
                            },
                            "workflow_id": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true,
                              "description": "Le workflow exécuté par la session."
                            },
                            "email": {
                              "type": "string",
                              "format": "email",
                              "description": "L'adresse à laquelle le lien a été envoyé."
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "Created": {
                    "value": {
                      "didit_internal_id": "f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418",
                      "vendor_data": "user-abc-123",
                      "display_name": null,
                      "full_name": "John Doe",
                      "date_of_birth": null,
                      "effective_name": "John Doe",
                      "status": "ACTIVE",
                      "metadata": {},
                      "portrait_image_url": null,
                      "session_count": 0,
                      "approved_count": 0,
                      "declined_count": 0,
                      "in_review_count": 0,
                      "issuing_states": [],
                      "approved_emails": [],
                      "approved_phones": [],
                      "features": {},
                      "features_list": [],
                      "last_session_at": null,
                      "last_activity_at": "2025-06-15T10:30:00Z",
                      "first_session_at": null,
                      "tags": [],
                      "comments": [],
                      "created_at": "2025-06-15T10:30:00Z",
                      "updated_at": "2025-06-15T10:30:00Z",
                      "verification_link": null
                    }
                  },
                  "Created with verification link": {
                    "value": {
                      "didit_internal_id": "9b2f6c1e-3d4a-4e5f-8a7b-1c2d3e4f5a6b",
                      "vendor_data": "user-abc-789",
                      "display_name": null,
                      "full_name": "Julia Martin",
                      "date_of_birth": null,
                      "effective_name": "Julia Martin",
                      "status": "ACTIVE",
                      "metadata": {
                        "contact": {
                          "email": "julia.martin@example.com"
                        }
                      },
                      "portrait_image_url": null,
                      "session_count": 1,
                      "approved_count": 0,
                      "declined_count": 0,
                      "in_review_count": 0,
                      "issuing_states": [],
                      "approved_emails": [],
                      "approved_phones": [],
                      "features": {},
                      "features_list": [],
                      "last_session_at": "2025-06-15T10:30:00Z",
                      "last_activity_at": "2025-06-15T10:30:00Z",
                      "first_session_at": "2025-06-15T10:30:00Z",
                      "tags": [],
                      "comments": [],
                      "created_at": "2025-06-15T10:30:00Z",
                      "updated_at": "2025-06-15T10:30:00Z",
                      "verification_link": {
                        "session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa7",
                        "session_number": 43762,
                        "status": "Not Started",
                        "url": "https://verify.didit.me/en/session/3FaJ9wLqX2Mz",
                        "workflow_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                        "email": "julia.martin@example.com"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide, indexé par champ : généralement un `vendor_data` en double, un champ obligatoire manquant ou une valeur malformée. Avec `send_verification_link: true`, également un `email` ou un `workflow_id` manquant, un workflow inconnu ou de Vérification d'entreprise (KYB), une `language` non prise en charge (indexée sous `contact_details.email_lang`), un `vendor_data` sur liste de blocage, ou un nombre insuffisant de crédits pour démarrer la session. Rien n'est écrit.",
            "content": {
              "application/json": {
                "examples": {
                  "Duplicate": {
                    "value": {
                      "vendor_data": [
                        "A user with this vendor_data already exists."
                      ]
                    }
                  },
                  "Missing vendor_data": {
                    "value": {
                      "vendor_data": [
                        "This field is required."
                      ]
                    }
                  },
                  "Bad metadata": {
                    "value": {
                      "metadata": [
                        "Metadata must be a JSON object."
                      ]
                    }
                  },
                  "Bad status": {
                    "value": {
                      "status": [
                        "Invalid status. Valid options are: ACTIVE, FLAGGED, BLOCKED"
                      ]
                    }
                  },
                  "Bad country": {
                    "value": {
                      "country": [
                        "Use an ISO 3166 country code, like ES or ESP."
                      ]
                    }
                  },
                  "Contact not an object": {
                    "value": {
                      "email": [
                        "metadata.contact must be a JSON object to store this value."
                      ]
                    }
                  },
                  "Address not an object": {
                    "value": {
                      "country": [
                        "metadata.address must be a JSON object to store this value."
                      ]
                    }
                  },
                  "Link without email or workflow": {
                    "value": {
                      "email": [
                        "An email address is required to send a verification link."
                      ],
                      "workflow_id": [
                        "Pick the workflow to send a verification link for."
                      ]
                    }
                  },
                  "Unknown workflow": {
                    "value": {
                      "workflow_id": [
                        "Invalid workflow_id."
                      ]
                    }
                  },
                  "Business workflow": {
                    "value": {
                      "workflow_id": [
                        "This workflow verifies a business. Pick a workflow that verifies a person to send them a verification link."
                      ]
                    }
                  },
                  "Blocklisted vendor_data": {
                    "value": {
                      "vendor_data": "This user or business has been blocked and cannot create new verification sessions."
                    }
                  },
                  "Insufficient credits": {
                    "value": {
                      "detail": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Aucun identifiant fourni. Les requêtes vers les chemins `/v3/users/*` sans en-tête `x-api-key` (ou token `Authorization: Bearer`) sont rejetées par le middleware d'authentification avant d'atteindre l'API.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing credentials": {
                    "value": {
                      "detail": "You must be authenticated with a valid access token to access this endpoint."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API non valide ou révoquée, ou la clé ne peut pas créer d'utilisateurs pour cette application. Une clé API avec permissions restreintes nécessite l'écriture sur `users`, ainsi que l'écriture sur `sessions` lorsque `send_verification_link` est `true` ; rien n'est écrit. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "No sessions write": {
                    "summary": "Une clé restreinte demande un lien de vérification sans droit d'écriture sur les sessions",
                    "value": {
                      "detail": "This API key has no write access to sessions."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez après l'intervalle indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/vendor-users/by-id/{didit_internal_id}/faces/upload/": {
      "post": {
        "summary": "Téléverser le visage de l'utilisateur",
        "description": "Associez une image de visage importée et de confiance à un profil utilisateur existant. Utilisez cette action après avoir créé ou récupéré un utilisateur via `vendor_data` et lu son `didit_internal_id`. Le visage téléversé est stocké sur le profil utilisateur et indexé pour la détection de doublons et la recherche faciale. Il n'est pas ajouté à une liste de blocage de visages.",
        "operationId": "upload_user_face",
        "x-didit-sdk": {
          "resource": "users",
          "method": "upload_face",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation propriétaire de l'application."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application à laquelle appartient le profil utilisateur."
          },
          {
            "name": "didit_internal_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID interne de l'utilisateur Didit, renvoyé sous la forme `didit_internal_id` par `GET /v3/users/{vendor_data}/` et `POST /v3/users/create/`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "image"
                ],
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "byte",
                    "description": "Image faciale JPG ou PNG brute encodée en base64. N'incluez pas le préfixe `data:image/...;base64,`. Taille maximale décodée : 2 MB."
                  },
                  "comment": {
                    "type": "string",
                    "description": "Note optionnelle visible par l'opérateur pour le visage téléversé.",
                    "default": ""
                  }
                }
              },
              "examples": {
                "Imported face": {
                  "summary": "Associer un visage importé d'un précédent fournisseur",
                  "value": {
                    "image": "/9j/4AAQSkZJRgABAQEA...",
                    "comment": "Imported from previous KYC provider"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/vendor-users/by-id/f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418/faces/upload/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"image\": \"/9j/4AAQSkZJRgABAQEA...\", \"comment\": \"Imported from previous KYC provider\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.users.upload_face(\n    \"11111111-2222-3333-4444-555555555555\",\n    image=\"/9j/4AAQSkZJRgABAQEA...\",\n    comment=\"Imported from previous KYC provider\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.users.uploadFace(\"11111111-2222-3333-4444-555555555555\", {\n  image: \"/9j/4AAQSkZJRgABAQEA...\",\n  comment: \"Imported from previous KYC provider\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Users.UploadFace(ctx, \"11111111-2222-3333-4444-555555555555\", didit.UsersUploadFaceParams{\n\tImage:   \"/9j/4AAQSkZJRgABAQEA...\",\n\tComment: didit.String(\"Imported from previous KYC provider\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.UsersUploadFaceParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.users().uploadFace(\"11111111-2222-3333-4444-555555555555\", UsersUploadFaceParams.builder()\n        .image(\"/9j/4AAQSkZJRgABAQEA...\")\n        .comment(\"Imported from previous KYC provider\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->users->uploadFace('11111111-2222-3333-4444-555555555555', [\n    'image' => '/9j/4AAQSkZJRgABAQEA...',\n    'comment' => 'Imported from previous KYC provider',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.users.upload_face(\n  \"11111111-2222-3333-4444-555555555555\",\n  image: \"/9j/4AAQSkZJRgABAQEA...\",\n  comment: \"Imported from previous KYC provider\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Users.UploadFaceAsync(\"11111111-2222-3333-4444-555555555555\", new UsersUploadFaceParams\n{\n    Image = \"/9j/4AAQSkZJRgABAQEA...\",\n    Comment = \"Imported from previous KYC provider\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Visage téléversé et associé au profil utilisateur.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "uuid",
                    "image_url",
                    "comment",
                    "uploaded_by",
                    "created_at"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid",
                      "description": "UUID de l'enregistrement de visage de l'utilisateur téléversé."
                    },
                    "image_url": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL signée pour l'image du visage téléversée."
                    },
                    "comment": {
                      "type": "string",
                      "nullable": true,
                      "description": "Commentaire fourni lors du téléversement du visage."
                    },
                    "uploaded_by": {
                      "type": "string",
                      "nullable": true,
                      "description": "E-mail ou identifiant de l'auteur du téléversement lorsqu'il est disponible."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Horodatage du téléversement."
                    }
                  }
                },
                "examples": {
                  "Uploaded": {
                    "value": {
                      "uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                      "image_url": "https://signed-url.example/face.jpg",
                      "comment": "Imported from previous KYC provider",
                      "uploaded_by": "api",
                      "created_at": "2026-05-18T12:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Corps de requête ou image non valide. Causes courantes : base64 non valide, image non valide, aucun visage détectable, image de plus de 2 Mo, embedding manquant, ou l'utilisateur a déjà téléversé 5 visages.",
            "content": {
              "application/json": {
                "examples": {
                  "No face": {
                    "value": {
                      "image": "No face detected in the image. Please upload a clear photo with a visible face."
                    }
                  },
                  "Too many faces": {
                    "value": {
                      "detail": "Maximum of 5 faces per user reached."
                    }
                  },
                  "Too large": {
                    "value": {
                      "image": "Image exceeds maximum size of 2 MB."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing key": {
                    "value": {
                      "detail": "Authentication credentials were not provided."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'identifiant d'authentification est valide, mais ne peut pas écrire de profils d'utilisateurs pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun utilisateur n'existe pour ce `didit_internal_id` dans l'application.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée ; réduisez la cadence et réessayez.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "Request was throttled. Expected available in 30 seconds."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/update-data/": {
      "patch": {
        "summary": "Mettre à jour les données KYC extraites du document d'identité lors d'une session de vérification",
        "description": "Corrigez les champs d'identité extraits (OCR / NFC) de la pièce d'identité de l'utilisateur — noms mal lus, dates, numéros de document, etc. — une fois la vérification terminée. Les appelants habituels sont un analyste de conformité travaillant depuis votre propre back-office ou une tâche de rapprochement automatisée. Chaque champ du corps est facultatif : seules les clés envoyées sont écrites, tout le reste est laissé intact (sémantique `PATCH`).\n\nLa session doit appartenir à votre application et avoir le statut `Approved`, `Declined`, `In Review` ou `Kyc Expired`. Les sessions dans tout autre état (par exemple encore `In Progress`) renvoient `404` avec `\"No Session matches the given query.\"` — à distinguer du `\"Not found.\"` renvoyé pour un `sessionId` inconnu ou supprimé. La session doit également comporter un enregistrement de vérification d'identité (KYC) : les sessions dont le workflow n'a jamais exécuté d'étape de vérification d'identité renvoient `404` (`\"The session does not have a KYC.\"`). Pour les workflows de graphe comportant plusieurs étapes de vérification d'identité, ciblez une étape spécifique avec `node_id` (paramètre de requête ou champ du corps) ; lorsqu'il est omis, l'enregistrement KYC le plus récent est mis à jour.\n\nDeux champs dérivés sont recalculés à chaque appel : `full_name` (à partir de `first_name` + `last_name`) et `issuing_state_name` (à partir de `issuing_state`). Si le champ texte libre `address` change, le serveur peut également recalculer son géocodage et actualiser `parsed_address` (ignoré pour les sessions de sandbox). `extra_fields` et `parsed_address` sont fusionnés clé par clé plutôt que remplacés — consultez les descriptions champ par champ pour connaître la sémantique de suppression par `null`.\n\nLa soumission d'au moins un champ valide déclenche le [webhook](/fr/integration/webhooks) `data.updated` (déclencheur `manual_review`) — même lorsque les valeurs soumises sont identiques à celles enregistrées. Lorsque les valeurs changent réellement, une entrée d'activité `KYC_DATA_UPDATED` consignant les champs modifiés avec leurs valeurs précédentes et nouvelles est ajoutée aux `reviews` de la session, visible dans [Get Decision](#get-/v3/session/-sessionId-/decision/) et dans la chronologie d'activité de la console. Le statut et la décision de la session ne sont **pas** réévalués — utilisez [Update Status](#patch-/v3/session/-sessionId-/update-status/) pour modifier le résultat. Un corps JSON vide (`{}`) est accepté et renvoie simplement les données KYC actuelles sans déclencher le webhook.\n\nAccepte une clé API ou un token d'utilisateur de la console ; dans les deux cas, l'identifiant doit disposer de l'autorisation `write:sessions`. Les échecs d'authentification et d'autorisation renvoient tous deux `403` — cette API ne répond jamais `401`. Notez que la recherche de la session a lieu avant la vérification des identifiants, de sorte qu'un `sessionId` inconnu renvoie `404` même si les identifiants sont manquants. Cet endpoint a une limite de débit dédiée de 10 requêtes par minute par clé API (les requêtes invalides comptent également) ; le budget d'écriture partagé de 300 requêtes par minute s'applique également.",
        "operationId": "patch_v3_session_update_data",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_data",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification des utilisateurs (KYC) dont vous corrigez les données extraites du document. Les identifiants de session de Vérification d'entreprise (KYB) ne sont pas valides ici — pour les données d'entreprise, utilisez [Mettre à jour les données d'entreprise KYB](#patch-/v3/session/-sessionId-/kyb/-companyUuid-/update-data/).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud du graphe de workflow dont l'enregistrement KYC doit être modifié, pour les workflows basés sur un graphe comportant plusieurs étapes de vérification d'identité (également accepté en tant que champ `node_id` dans le corps). En cas d'omission, l'enregistrement KYC le plus récent de la session est modifié. Si aucun KYC n'existe pour le nœud indiqué, l'appel renvoie `404` (`\"The session does not have a KYC for node '<node_id>'.\"`).",
            "schema": {
              "type": "string",
              "example": "feature_ocr"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Tous les champs sont facultatifs : envoyez uniquement ce que vous souhaitez modifier.",
                "properties": {
                  "document_type": {
                    "type": "string",
                    "description": "Code du type de document. Accepte les codes courts listés dans l'enum, ainsi que six alias au format long normalisés côté serveur avant validation : `Passport` → `P`, `Identity Card` → `ID`, `Driver's License` → `DL`, `Residence Permit` → `RP`, `Health Insurance Card` → `HIC`, `Tax Card` → `TC`. Toute autre valeur (y compris `PASSPORT` en majuscules) renvoie `400`.",
                    "enum": [
                      "P",
                      "DL",
                      "ID",
                      "RP",
                      "SSC",
                      "HIC",
                      "WP",
                      "TC",
                      "VISA",
                      "PSC",
                      "BC",
                      "OTHER"
                    ],
                    "nullable": true,
                    "example": "P"
                  },
                  "document_subtype": {
                    "type": "string",
                    "maxLength": 128,
                    "nullable": true,
                    "description": "Sous-type de document issu du registre de documents, incluant le préfixe régional lorsque le registre distingue les variantes régionales."
                  },
                  "document_number": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Numéro de document tel qu'imprimé sur la pièce d'identité.",
                    "example": "PAB123456"
                  },
                  "personal_number": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Numéro d'identification personnel / national lorsque le document en comporte un (par ex. le DNI espagnol sur un passeport).",
                    "example": "99999999R"
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Date de naissance en `YYYY-MM-DD`. Tout autre format renvoie `400`.",
                    "example": "1980-01-01"
                  },
                  "date_of_issue": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Date de délivrance du document au format `YYYY-MM-DD`."
                  },
                  "expiration_date": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Date d'expiration du document au format `YYYY-MM-DD`."
                  },
                  "issuing_state": {
                    "type": "string",
                    "nullable": true,
                    "description": "Pays de délivrance sous forme de code ISO 3166-1 alpha-3. Insensible à la casse (`esp` est stocké sous la forme `ESP`) ; le `issuing_state_name` lisible par l'humain affiché dans [Obtenir la décision](#get-/v3/session/-sessionId-/decision/) est recalculé à partir de cette valeur. Les codes non valides renvoient `400`.",
                    "example": "ESP"
                  },
                  "first_name": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Prénom(s). Le `full_name` stocké est recalculé sous la forme `first_name + ' ' + last_name` à chaque appel à cet endpoint.",
                    "example": "Carmen"
                  },
                  "last_name": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Nom(s) de famille. Alimente également le `full_name` recalculé.",
                    "example": "Espanola Espanola"
                  },
                  "gender": {
                    "type": "string",
                    "enum": [
                      "M",
                      "F",
                      "U"
                    ],
                    "nullable": true,
                    "description": "Sexe tel qu'imprimé sur le document : `M` (masculin), `F` (féminin) ou `U` (inconnu). Toute autre valeur — y compris `X` — renvoie `400`."
                  },
                  "address": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Adresse en texte libre telle qu'imprimée sur le document. Lorsque cette valeur change (sessions hors sandbox uniquement) et que l'adresse structurée est encore manquante ou incomplète, le serveur la géocode à nouveau de manière synchrone avant de répondre — le corps de la réponse 200 reflète déjà l'adresse `parsed_address` actualisée. Le nouveau géocodage nécessite également que `issuing_state` soit présent sur l'enregistrement KYC."
                  },
                  "place_of_birth": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Lieu de naissance tel qu'imprimé sur le document."
                  },
                  "nationality": {
                    "type": "string",
                    "maxLength": 32,
                    "nullable": true,
                    "description": "Nationalité telle qu'imprimée sur le document. Texte libre jusqu'à 32 caractères — généralement un code ISO 3166-1 alpha-3 (par ex. `ESP`), mais non validé en tant que tel."
                  },
                  "marital_status": {
                    "type": "string",
                    "enum": [
                      "SINGLE",
                      "MARRIED",
                      "DIVORCED",
                      "WIDOWED",
                      "UNKNOWN"
                    ],
                    "description": "État civil lorsque le document le mentionne. Toute autre valeur renvoie `400`."
                  },
                  "extra_fields": {
                    "type": "object",
                    "additionalProperties": true,
                    "nullable": true,
                    "description": "Remplacements par clé pour les champs supplémentaires propres au document (par ex. `blood_group`, `dl_categories`, `mrz_string`). Les clés sont fusionnées dans la table de remplacement existante : envoyez une clé avec une valeur pour la définir, ou avec `null` / `\"\"` pour supprimer cette clé de la vue fusionnée. Envoyez l'ensemble du champ sous la valeur `null` pour effacer tous les remplacements précédemment appliqués. Doit être un objet JSON, sous peine de renvoyer `400`. La réponse renvoie toujours la vue fusionnée (valeurs extraites par OCR avec vos remplacements appliqués)."
                  },
                  "parsed_address": {
                    "type": "object",
                    "nullable": true,
                    "description": "Adresse structurée. Seules ces clés imbriquées sont acceptées : `address_type`, `city`, `region`, `street_1`, `street_2`, `postal_code`, `country` — toute autre clé renvoie `400`. Sémantique par clé : une valeur définit la clé, `null` la supprime. `formatted_address` est recalculée côté serveur en concaténant `street_1`, `street_2`, `city`, `region`, `postal_code` et `country` et est retournée dans la réponse — vous ne pouvez pas la définir directement.",
                    "properties": {
                      "address_type": {
                        "type": "string",
                        "nullable": true,
                        "description": "Classification d'adresse en texte libre (par ex. `home`)."
                      },
                      "city": {
                        "type": "string",
                        "nullable": true,
                        "example": "Madrid"
                      },
                      "region": {
                        "type": "string",
                        "nullable": true,
                        "description": "État / province / communauté autonome."
                      },
                      "street_1": {
                        "type": "string",
                        "nullable": true,
                        "example": "Avda de Madrid 34"
                      },
                      "street_2": {
                        "type": "string",
                        "nullable": true
                      },
                      "postal_code": {
                        "type": "string",
                        "nullable": true,
                        "example": "28013"
                      },
                      "country": {
                        "type": "string",
                        "nullable": true,
                        "description": "Code pays ISO 3166-1 alpha-2. Les entrées en minuscules sont normalisées en majuscules ; les codes alpha-3 sont rejetés avec une erreur `400`.",
                        "example": "ES"
                      }
                    }
                  }
                }
              },
              "examples": {
                "Correct name and DOB": {
                  "summary": "Corriger le nom, la date de naissance et l'adresse structurée mal lus par l'OCR",
                  "value": {
                    "first_name": "Carmen",
                    "last_name": "Espanola Espanola",
                    "date_of_birth": "1980-01-01",
                    "issuing_state": "ESP",
                    "marital_status": "MARRIED",
                    "extra_fields": {
                      "blood_group": "O+"
                    },
                    "parsed_address": {
                      "street_1": "Avda de Madrid 34",
                      "city": "Madrid",
                      "postal_code": "28013",
                      "country": "ES"
                    }
                  }
                },
                "Remove an extra field": {
                  "summary": "Supprimer une clé de champ supplémentaire, conserver le reste",
                  "value": {
                    "extra_fields": {
                      "blood_group": null
                    }
                  }
                },
                "Long-form document type": {
                  "summary": "L'alias long est normalisé vers le code court (ici P)",
                  "value": {
                    "document_type": "Passport"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Données KYC mises à jour. Renvoie l'**enregistrement KYC actuel complet** (chaque champ modifiable avec sa valeur stockée, plus les `extra_fields` fusionnés et l'adresse `parsed_address` actuelle) — pas seulement les champs que vous avez soumis. Le webhook `data.updated` se déclenche lorsqu'au moins un champ valide était présent dans le payload.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "document_type": {
                      "type": "string",
                      "description": "Code du type de document. Accepte les codes courts listés dans l'enum, ainsi que six alias au format long normalisés côté serveur avant validation : `Passport` → `P`, `Identity Card` → `ID`, `Driver's License` → `DL`, `Residence Permit` → `RP`, `Health Insurance Card` → `HIC`, `Tax Card` → `TC`. Toute autre valeur (y compris `PASSPORT` en majuscules) renvoie `400`.",
                      "enum": [
                        "P",
                        "DL",
                        "ID",
                        "RP",
                        "SSC",
                        "HIC",
                        "WP",
                        "TC",
                        "VISA",
                        "PSC",
                        "BC",
                        "OTHER"
                      ],
                      "nullable": true,
                      "example": "P"
                    },
                    "document_subtype": {
                      "type": "string",
                      "maxLength": 128,
                      "nullable": true,
                      "description": "Sous-type de document issu du registre de documents, incluant le préfixe régional lorsque le registre distingue les variantes régionales."
                    },
                    "document_number": {
                      "type": "string",
                      "maxLength": 255,
                      "nullable": true,
                      "description": "Numéro de document tel qu'imprimé sur la pièce d'identité.",
                      "example": "PAB123456"
                    },
                    "personal_number": {
                      "type": "string",
                      "maxLength": 255,
                      "nullable": true,
                      "description": "Numéro d'identification personnel / national lorsque le document en comporte un (par ex. le DNI espagnol sur un passeport).",
                      "example": "99999999R"
                    },
                    "date_of_birth": {
                      "type": "string",
                      "format": "date",
                      "nullable": true,
                      "description": "Date de naissance en `YYYY-MM-DD`. Tout autre format renvoie `400`.",
                      "example": "1980-01-01"
                    },
                    "date_of_issue": {
                      "type": "string",
                      "format": "date",
                      "nullable": true,
                      "description": "Date de délivrance du document au format `YYYY-MM-DD`."
                    },
                    "expiration_date": {
                      "type": "string",
                      "format": "date",
                      "nullable": true,
                      "description": "Date d'expiration du document au format `YYYY-MM-DD`."
                    },
                    "issuing_state": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pays de délivrance sous forme de code ISO 3166-1 alpha-3. Insensible à la casse (`esp` est stocké sous la forme `ESP`) ; le `issuing_state_name` lisible par l'humain affiché dans [Obtenir la décision](#get-/v3/session/-sessionId-/decision/) est recalculé à partir de cette valeur. Les codes non valides renvoient `400`.",
                      "example": "ESP"
                    },
                    "first_name": {
                      "type": "string",
                      "maxLength": 255,
                      "nullable": true,
                      "description": "Prénom(s). Le `full_name` stocké est recalculé sous la forme `first_name + ' ' + last_name` à chaque appel à cet endpoint.",
                      "example": "Carmen"
                    },
                    "last_name": {
                      "type": "string",
                      "maxLength": 255,
                      "nullable": true,
                      "description": "Nom(s) de famille. Alimente également le `full_name` recalculé.",
                      "example": "Espanola Espanola"
                    },
                    "gender": {
                      "type": "string",
                      "enum": [
                        "M",
                        "F",
                        "U"
                      ],
                      "nullable": true,
                      "description": "Sexe tel qu'imprimé sur le document : `M` (masculin), `F` (féminin) ou `U` (inconnu). Toute autre valeur — y compris `X` — renvoie `400`."
                    },
                    "address": {
                      "type": "string",
                      "maxLength": 255,
                      "nullable": true,
                      "description": "Adresse en texte libre telle qu'imprimée sur le document. Lorsque cette valeur change (sessions hors sandbox uniquement) et que l'adresse structurée est encore manquante ou incomplète, le serveur la géocode à nouveau en arrière-plan de la même requête et peut écraser `parsed_address` avec le résultat du géocodeur."
                    },
                    "place_of_birth": {
                      "type": "string",
                      "maxLength": 255,
                      "nullable": true,
                      "description": "Lieu de naissance tel qu'imprimé sur le document."
                    },
                    "nationality": {
                      "type": "string",
                      "maxLength": 32,
                      "nullable": true,
                      "description": "Nationalité telle qu'imprimée sur le document. Texte libre jusqu'à 32 caractères — généralement un code ISO 3166-1 alpha-3 (par ex. `ESP`), mais non validé en tant que tel."
                    },
                    "marital_status": {
                      "type": "string",
                      "enum": [
                        "SINGLE",
                        "MARRIED",
                        "DIVORCED",
                        "WIDOWED",
                        "UNKNOWN"
                      ],
                      "description": "État civil lorsque le document le mentionne. Toute autre valeur renvoie `400`."
                    },
                    "extra_fields": {
                      "type": "object",
                      "additionalProperties": true,
                      "nullable": true,
                      "description": "Vue fusionnée des champs supplémentaires du document : les valeurs extraites par OCR avec tous les remplacements manuels de l'opérateur appliqués. Les clés supprimées via un remplacement `null` sont absentes de ce mappage."
                    },
                    "parsed_address": {
                      "type": "object",
                      "nullable": true,
                      "description": "Adresse structurée actuelle (sans les clés internes de suivi), ou `null` si aucune n'existe. Comprend le champ recalculé `formatted_address` ainsi que les sept clés modifiables.",
                      "properties": {
                        "address_type": {
                          "type": "string",
                          "nullable": true,
                          "description": "Classification d'adresse en texte libre (par ex. `home`)."
                        },
                        "city": {
                          "type": "string",
                          "nullable": true,
                          "example": "Madrid"
                        },
                        "region": {
                          "type": "string",
                          "nullable": true,
                          "description": "État / province / communauté autonome."
                        },
                        "street_1": {
                          "type": "string",
                          "nullable": true,
                          "example": "Avda de Madrid 34"
                        },
                        "street_2": {
                          "type": "string",
                          "nullable": true
                        },
                        "postal_code": {
                          "type": "string",
                          "nullable": true,
                          "example": "28013"
                        },
                        "country": {
                          "type": "string",
                          "nullable": true,
                          "description": "Code pays ISO 3166-1 alpha-2. Les entrées en minuscules sont normalisées en majuscules ; les codes alpha-3 sont rejetés avec une erreur `400`.",
                          "example": "ES"
                        },
                        "formatted_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Forme assemblée et lisible par l'humain de l'adresse structurée. Recalculée côté serveur après chaque modification de `parsed_address`.",
                          "example": "Avda de Madrid 34, Madrid, 28013, ES"
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Updated KYC": {
                    "summary": "Dossier KYC complet après la correction",
                    "value": {
                      "document_type": "P",
                      "document_subtype": null,
                      "document_number": "PAB123456",
                      "personal_number": "99999999R",
                      "date_of_birth": "1980-01-01",
                      "date_of_issue": "2021-02-09",
                      "expiration_date": "2031-02-08",
                      "issuing_state": "ESP",
                      "first_name": "Carmen",
                      "last_name": "Espanola Espanola",
                      "gender": "F",
                      "address": "AVDA DE MADRID 34, MADRID, MADRID 28013",
                      "place_of_birth": "MADRID",
                      "nationality": "ESP",
                      "marital_status": "MARRIED",
                      "extra_fields": {
                        "mrz_string": "P<ESPESPANOLA<<CARMEN<<<<<",
                        "blood_group": "O+"
                      },
                      "parsed_address": {
                        "city": "Madrid",
                        "street_1": "Avda de Madrid 34",
                        "postal_code": "28013",
                        "country": "ES",
                        "formatted_address": "Avda de Madrid 34, Madrid, 28013, ES"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les erreurs de champ sont renvoyées sous la forme `{\"<field>\": [\"<message>\"]}` ; les erreurs sur les clés imbriquées de `parsed_address` / `extra_fields` utilisent un objet : `{\"parsed_address\": {\"<key>\": \"<message>\"}}`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid gender": {
                    "summary": "gender doit être M, F ou U",
                    "value": {
                      "gender": [
                        "\"X\" is not a valid choice."
                      ]
                    }
                  },
                  "Invalid document type": {
                    "summary": "Ni un code court ni un alias long",
                    "value": {
                      "document_type": [
                        "\"PASSPORT\" is not a valid choice."
                      ]
                    }
                  },
                  "Invalid issuing state": {
                    "summary": "issuing_state n'est pas au format ISO 3166-1 alpha-3",
                    "value": {
                      "issuing_state": [
                        "Invalid ISO 3166-1 alpha-3 country code for issuing_state."
                      ]
                    }
                  },
                  "Invalid marital status": {
                    "summary": "marital_status n'appartient pas à l'énumération",
                    "value": {
                      "marital_status": [
                        "\"ENGAGED\" is not a valid choice."
                      ]
                    }
                  },
                  "Bad date format": {
                    "summary": "Les dates doivent être au format YYYY-MM-DD",
                    "value": {
                      "date_of_birth": [
                        "Date has wrong format. Use one of these formats instead: YYYY-MM-DD."
                      ]
                    }
                  },
                  "Unsupported parsed_address key": {
                    "summary": "Seules les sept clés documentées sont autorisées",
                    "value": {
                      "parsed_address": {
                        "zipcode": "Unsupported key. Allowed keys: address_type, city, region, street_1, street_2, postal_code, country"
                      }
                    }
                  },
                  "Invalid parsed_address country": {
                    "summary": "Le pays imbriqué doit être au format alpha-2, pas alpha-3",
                    "value": {
                      "parsed_address": {
                        "country": "Invalid ISO 3166-1 alpha-2 country code."
                      }
                    }
                  },
                  "extra_fields not an object": {
                    "summary": "extra_fields doit être un objet JSON",
                    "value": {
                      "extra_fields": [
                        "This field must be a JSON object."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants ou autorisations insuffisantes. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'identifiant ne dispose pas de write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Session inconnue, session dans un état non modifiable, ou aucun enregistrement KYC à modifier. Chaque cas dispose d'un message `detail` distinct (voir exemples). La recherche de la session inconnue est exécutée avant les vérifications des identifiants.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID dans votre application (ou elle a été supprimée)",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Wrong session state": {
                    "summary": "La session existe mais n'est pas Approved / Declined / In Review / Kyc Expired",
                    "value": {
                      "detail": "No Session matches the given query."
                    }
                  },
                  "No KYC record": {
                    "summary": "Le workflow n'a jamais exécuté d'étape de Vérification d'identité",
                    "value": {
                      "detail": "The session does not have a KYC."
                    }
                  },
                  "No KYC for node": {
                    "summary": "node_id fourni mais aucun KYC n'existe pour celui-ci",
                    "value": {
                      "detail": "The session does not have a KYC for node 'feature_missing'."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dédiée dépassée — 10 mises à jour de données KYC par minute et par clé API (les requêtes rejetées sont décomptées du quota). Le quota partagé d'écriture de 300/min peut également se déclencher avec son propre message. Examinez `Retry-After` et les en-têtes de réponse `X-RateLimit-*` avant de réessayer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget de mise à jour KYC épuisé",
                    "value": {
                      "detail": "Session KYC data update rate limit exceeded. You can make up to 10 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/update-data/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"first_name\": \"Carmen\",\n    \"last_name\": \"Espanola Espanola\",\n    \"date_of_birth\": \"1980-01-01\",\n    \"issuing_state\": \"ESP\",\n    \"parsed_address\": {\n      \"street_1\": \"Avda de Madrid 34\",\n      \"city\": \"Madrid\",\n      \"postal_code\": \"28013\",\n      \"country\": \"ES\"\n    }\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_data(\n    \"11111111-2222-3333-4444-555555555555\",\n    date_of_birth=\"1980-01-01\",\n    issuing_state=\"ESP\",\n    first_name=\"Carmen\",\n    last_name=\"Espanola Espanola\",\n    marital_status=\"MARRIED\",\n    extra_fields={\"blood_group\": \"O+\"},\n    parsed_address={\n        \"city\": \"Madrid\",\n        \"street_1\": \"Avda de Madrid 34\",\n        \"postal_code\": \"28013\",\n        \"country\": \"ES\",\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateData(\"11111111-2222-3333-4444-555555555555\", {\n  date_of_birth: \"1980-01-01\",\n  issuing_state: \"ESP\",\n  first_name: \"Carmen\",\n  last_name: \"Espanola Espanola\",\n  marital_status: \"MARRIED\",\n  extra_fields: { blood_group: \"O+\" },\n  parsed_address: {\n    city: \"Madrid\",\n    street_1: \"Avda de Madrid 34\",\n    postal_code: \"28013\",\n    country: \"ES\",\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateData(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsUpdateDataParams{\n\tDateOfBirth:   didit.String(\"1980-01-01\"),\n\tIssuingState:  didit.String(\"ESP\"),\n\tFirstName:     didit.String(\"Carmen\"),\n\tLastName:      didit.String(\"Espanola Espanola\"),\n\tMaritalStatus: didit.Some(didit.SessionsUpdateDataParamsMaritalStatus(\"MARRIED\")),\n\tExtraFields:   didit.Some(map[string]any{\"blood_group\": \"O+\"}),\n\tParsedAddress: didit.Some(didit.SessionsUpdateDataParamsParsedAddress{\n\t\tCity:       didit.String(\"Madrid\"),\n\t\tStreet1:    didit.String(\"Avda de Madrid 34\"),\n\t\tPostalCode: didit.String(\"28013\"),\n\t\tCountry:    didit.String(\"ES\"),\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.LocalDate;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.SessionsUpdateDataParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateData(\"11111111-2222-3333-4444-555555555555\", SessionsUpdateDataParams.builder()\n        .dateOfBirth(LocalDate.parse(\"1980-01-01\"))\n        .issuingState(\"ESP\")\n        .firstName(\"Carmen\")\n        .lastName(\"Espanola Espanola\")\n        .maritalStatus(SessionsUpdateDataParams.MaritalStatus.of(\"MARRIED\"))\n        .extraFields(Map.of(\"blood_group\", \"O+\"))\n        .parsedAddress(SessionsUpdateDataParams.ParsedAddress.builder()\n                .city(\"Madrid\")\n                .street1(\"Avda de Madrid 34\")\n                .postalCode(\"28013\")\n                .country(\"ES\")\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateData('11111111-2222-3333-4444-555555555555', [\n    'date_of_birth' => '1980-01-01',\n    'issuing_state' => 'ESP',\n    'first_name' => 'Carmen',\n    'last_name' => 'Espanola Espanola',\n    'marital_status' => 'MARRIED',\n    'extra_fields' => ['blood_group' => 'O+'],\n    'parsed_address' => [\n        'city' => 'Madrid',\n        'street_1' => 'Avda de Madrid 34',\n        'postal_code' => '28013',\n        'country' => 'ES',\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_data(\n  \"11111111-2222-3333-4444-555555555555\",\n  date_of_birth: \"1980-01-01\",\n  issuing_state: \"ESP\",\n  first_name: \"Carmen\",\n  last_name: \"Espanola Espanola\",\n  marital_status: \"MARRIED\",\n  extra_fields: { blood_group: \"O+\" },\n  parsed_address: {\n    city: \"Madrid\",\n    street_1: \"Avda de Madrid 34\",\n    postal_code: \"28013\",\n    country: \"ES\",\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateDataAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsUpdateDataParams\n{\n    DateOfBirth = \"1980-01-01\",\n    IssuingState = \"ESP\",\n    FirstName = \"Carmen\",\n    LastName = \"Espanola Espanola\",\n    MaritalStatus = new SessionsUpdateDataParamsMaritalStatus(\"MARRIED\"),\n    ExtraFields = new Dictionary<string, object> { [\"blood_group\"] = \"O+\" },\n    ParsedAddress = new SessionsUpdateDataParamsParsedAddress\n    {\n        City = \"Madrid\",\n        Street1 = \"Avda de Madrid 34\",\n        PostalCode = \"28013\",\n        Country = \"ES\",\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/features/{nodeId}/update-status/": {
      "patch": {
        "summary": "Mettre à jour le statut d'une fonctionnalité (étape) individuelle",
        "description": "Définissez le statut d'une fonctionnalité (étape) de vérification individuelle au sein d'une session. Ciblez la fonctionnalité par son `nodeId` dans le graphe du workflow. Sur les workflows sans graphe, dont les étapes n'ont pas de nœud, utilisez `default` et transmettez également `feature_type` pour indiquer l'étape concernée.\n\nFonctionne aussi bien pour les sessions de Vérification des utilisateurs (KYC) que pour celles de Vérification d'entreprise (KYB) et pour chaque type d'étape : ID/OCR, Détection du vivant, Correspondance faciale, NFC, AML, Justificatif de domicile, Téléphone, E-mail, Validation en base de données, Questionnaire, ainsi que les vérifications KYB de registre / documents / personnes clés. Cet endpoint n'est **pas** disponible pour les sessions API autonomes (`session_type = API`).\n\n`new_status` doit être l'un des suivants : `Approved`, `Declined` ou `In Review`, et doit différer du statut actuel de la fonctionnalité.\n\n**Quand la dérogation s'applique.** Sans `defer_until_flow_finishes` (ou avec `false`), la dérogation s'applique immédiatement, comme c'était déjà le cas ; lorsque la personne se trouve encore dans le flux, elle est enregistrée en tant que `forced`. Avec `defer_until_flow_finishes: true` pendant que la personne se trouve encore dans le flux (la session est `Not Started`, `In Progress` ou `Resubmitted` et n'est pas terminée), la dérogation est stockée en tant que `pending_until_flow_finishes` et s'applique à la fin du flux, après que le flux a atteint sa propre décision. Sur une session dont le flux s'est déjà terminé, elle s'applique immédiatement dans les deux cas. Une dérogation en attente est en revanche annulée lorsque la personne recommence son étape avant de terminer, lorsqu'une dérogation plus récente sur la même vérification la remplace, lorsque la session quitte le flux sans l'avoir terminé (abandonnée, expirée ou décidée en cours de flux), ou lorsque vous l'annulez avec `POST /v3/session/{sessionId}/features/overrides/{overrideId}/cancel/`. Listez les dérogations d'une session avec `GET /v3/session/{sessionId}/features/overrides/`.\n\n**Effet sur la session.** Une session qui a déjà une décision la conserve : seule la vérification change. Lorsque la session n'a pas encore de décision et que son workflow est précisément en attente de cette étape, l'application de la dérogation valide l'étape : le workflow se poursuit, les étapes ultérieures s'exécutent et un nœud de statut peut définir la décision de la session et déclencher `status.updated`.\n\n**Webhooks et activité.** Un webhook `data.updated` se déclenche lorsque la dérogation s'applique (immédiatement ou à la fin du flux), jamais pendant qu'elle est en attente ni lorsqu'elle est annulée. Chaque dérogation est enregistrée dans l'activité de la session sous la mention `FEATURE_OVERRIDE_PENDING`, `FEATURE_OVERRIDE_APPLIED` ou `FEATURE_OVERRIDE_CANCELLED`, avec l'auteur de l'action ; l'entrée de la requête contient votre `comment`.\n\nAuthentifiez-vous avec votre clé API (`x-api-key`) ou un en-tête d'autorisation utilisateur comportant le privilège `write:sessions` ; une clé API restreinte nécessite un accès en écriture aux décisions.",
        "operationId": "patch_v3_session_update_feature_status",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_feature_status",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB) — le service résout l'identifiant pour les deux types de session.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "in": "path",
            "name": "nodeId",
            "required": true,
            "description": "ID de nœud du graphe de workflow de la fonctionnalité à mettre à jour (par exemple `feature_ocr_1`). Utilisez la valeur littérale `default` pour les workflows sans graphe (à étape unique) où la fonctionnalité n'a pas d'ID de nœud.",
            "schema": {
              "type": "string",
              "example": "feature_ocr_1"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "new_status"
                ],
                "properties": {
                  "new_status": {
                    "type": "string",
                    "description": "Statut cible pour cette fonctionnalité. Doit être différent de la valeur actuelle.",
                    "enum": [
                      "Approved",
                      "Declined",
                      "In Review"
                    ],
                    "example": "Approved"
                  },
                  "comment": {
                    "type": "string",
                    "description": "Note en texte libre optionnelle enregistrée dans la piste d'examen de la session pour cette modification de fonctionnalité.",
                    "example": "Document manually verified by compliance."
                  },
                  "feature_type": {
                    "type": "string",
                    "enum": [
                      "ID_VERIFICATION",
                      "OCR",
                      "OCR_BACK",
                      "NFC",
                      "LIVENESS",
                      "FACE",
                      "AGE_ESTIMATION",
                      "AGE_VERIFICATION",
                      "FACE_SEARCH",
                      "FACE_MATCH",
                      "IP_ANALYSIS",
                      "AML",
                      "PHONE",
                      "PHONE_VERIFICATION",
                      "EMAIL",
                      "EMAIL_VERIFICATION",
                      "POA",
                      "PROOF_OF_ADDRESS",
                      "DATABASE_VALIDATION",
                      "DATA_VALIDATION",
                      "QUESTIONNAIRE",
                      "DOCUMENT_AI",
                      "KYB_REGISTRY",
                      "KYB_DOCUMENTS",
                      "KYB_KEY_PEOPLE",
                      "BANK_VERIFICATION",
                      "GEOLOCATION"
                    ],
                    "description": "Quel type d'étape cibler. Requis sur les workflows qui ne sont pas de type graphe (`nodeId` = `default`), où chaque étape ne partage aucun nœud ; facultatif sinon. Une valeur inconnue renvoie `400`.",
                    "example": "LIVENESS"
                  },
                  "defer_until_flow_finishes": {
                    "type": "boolean",
                    "default": false,
                    "description": "Tant que la personne est encore dans le flux, enregistrez la dérogation sous `pending_until_flow_finishes` et appliquez-la lorsque le flux se termine, plutôt qu'immédiatement. Si omis ou défini sur `false`, la dérogation s'applique immédiatement. Sur une session dont le flux est déjà terminé, elle s'applique immédiatement dans les deux cas.",
                    "example": false
                  }
                }
              },
              "examples": {
                "Apply Now": {
                  "summary": "Approuver immédiatement l'étape d'identité",
                  "value": {
                    "new_status": "Approved",
                    "comment": "Document manually verified by compliance."
                  }
                },
                "Wait For The Flow": {
                  "summary": "Approuver l'étape de détection du vivant une fois que la personne a terminé le parcours",
                  "value": {
                    "new_status": "Approved",
                    "comment": "Liveness retried with a reviewer present.",
                    "defer_until_flow_finishes": true
                  }
                },
                "Non-graph Workflow": {
                  "summary": "Cibler l'étape de détection du vivant d'un workflow sans nœuds (nodeId = default)",
                  "value": {
                    "new_status": "In Review",
                    "feature_type": "LIVENESS"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "La dérogation a été enregistrée. `new_status` est le statut de la vérification tel qu'enregistré : celui demandé une fois la dérogation appliquée, ou celui inchangé pendant qu'elle attend la fin du flux. `override` indique ce qui s'est produit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "node_id": {
                      "type": "string",
                      "nullable": true,
                      "description": "Le nœud de workflow de l'étape mise à jour, ou `null` pour une étape sans nœud (le chemin `default` dans un workflow sans graphe).",
                      "example": "feature_ocr_1"
                    },
                    "feature_type": {
                      "type": "string",
                      "description": "Nom du modèle de la fonctionnalité mise à jour (par ex. `KYC`, `Face`, `FaceMatch`, `AML`, `POA`).",
                      "example": "KYC"
                    },
                    "new_status": {
                      "type": "string",
                      "description": "Le statut stocké de la vérification : celui demandé une fois la dérogation appliquée, le statut inchangé tant que la dérogation attend la fin du flux.",
                      "example": "Approved"
                    },
                    "override": {
                      "$ref": "#/components/schemas/FeatureStatusOverride"
                    }
                  },
                  "required": [
                    "session_id",
                    "node_id",
                    "feature_type",
                    "new_status",
                    "override"
                  ]
                },
                "examples": {
                  "Applied": {
                    "summary": "La dérogation s'est appliquée immédiatement",
                    "value": {
                      "session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "node_id": "feature_ocr_1",
                      "feature_type": "KYC",
                      "new_status": "Approved",
                      "override": {
                        "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
                        "node_id": "feature_ocr_1",
                        "feature_type": "",
                        "feature_model": "KYC",
                        "previous_status": "In Review",
                        "new_status": "Approved",
                        "state": "applied",
                        "forced": false,
                        "reason": "Document manually verified by compliance.",
                        "requested_by": {
                          "email": "reviewer@example.com",
                          "name": "Alex Reviewer",
                          "type": "CONSOLE_USER"
                        },
                        "requested_at": "2026-10-13T09:15:00Z",
                        "applied_at": "2026-10-13T09:15:00Z",
                        "cancelled_at": null,
                        "cancel_reason": null
                      }
                    }
                  },
                  "Waiting For The Flow": {
                    "summary": "defer_until_flow_finishes alors que la personne est toujours dans le flux",
                    "value": {
                      "session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "node_id": "feature_liveness_1",
                      "feature_type": "Face",
                      "new_status": "Declined",
                      "override": {
                        "id": "9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3",
                        "node_id": "feature_liveness_1",
                        "feature_type": "",
                        "feature_model": "Face",
                        "previous_status": "Declined",
                        "new_status": "Approved",
                        "state": "pending_until_flow_finishes",
                        "forced": false,
                        "reason": "Liveness retried with a reviewer present.",
                        "requested_by": {
                          "email": "reviewer@example.com",
                          "name": "Alex Reviewer",
                          "type": "CONSOLE_USER"
                        },
                        "requested_at": "2026-10-13T09:15:00Z",
                        "applied_at": null,
                        "cancelled_at": null,
                        "cancel_reason": null
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Renvoyée lorsque `new_status` est invalide ou inchangé, lorsque `feature_type` est inconnu, ou lorsque la session est une session d'API autonome.",
            "content": {
              "application/json": {
                "examples": {
                  "Same Status": {
                    "summary": "new_status est identique au statut actuel",
                    "value": {
                      "new_status": [
                        "The new status is the same as the current status."
                      ]
                    }
                  },
                  "API Session": {
                    "summary": "Le statut de la fonctionnalité ne peut pas être modifié sur des sessions d'API autonomes",
                    "value": [
                      "Cannot change feature status for API sessions."
                    ]
                  },
                  "Unknown feature_type": {
                    "summary": "feature_type n'est pas un type d'étape connu",
                    "value": {
                      "feature_type": [
                        "Unknown feature_type 'SELFIE'."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API Key": {
                    "summary": "Clé API restreinte ayant dépassé sa date d'expiration",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants ou autorisations insuffisantes.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "La clé API ne dispose pas de l'autorisation write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped Key Without Access": {
                    "summary": "Clé API restreinte sans accès en écriture aux décisions",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'a pas été trouvée, ou elle ne possède aucune fonctionnalité avec le `nodeId` indiqué.",
            "content": {
              "application/json": {
                "examples": {
                  "Session Not Found": {
                    "summary": "session_id inconnu",
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "Feature Not Found": {
                    "summary": "Aucune fonctionnalité pour ce node_id",
                    "value": {
                      "detail": "No feature found with node_id 'feature_ocr_1' in this session."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/features/feature_ocr_1/update-status/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"new_status\": \"Approved\",\n    \"comment\": \"Document manually verified by compliance.\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_feature_status(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"feature_ocr_1\",\n    new_status=\"Approved\",\n    comment=\"Document manually verified by compliance.\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateFeatureStatus(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_ocr_1\",\n  {\n    new_status: \"Approved\",\n    comment: \"Document manually verified by compliance.\",\n  },\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateFeatureStatus(ctx, \"11111111-2222-3333-4444-555555555555\", \"feature_ocr_1\", didit.SessionsUpdateFeatureStatusParams{\n\tNewStatus: \"Approved\",\n\tComment:   didit.String(\"Document manually verified by compliance.\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsUpdateFeatureStatusParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateFeatureStatus(\"11111111-2222-3333-4444-555555555555\", \"feature_ocr_1\", SessionsUpdateFeatureStatusParams.builder()\n        .newStatus(SessionsUpdateFeatureStatusParams.NewStatus.of(\"Approved\"))\n        .comment(\"Document manually verified by compliance.\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateFeatureStatus('11111111-2222-3333-4444-555555555555', 'feature_ocr_1', [\n    'new_status' => 'Approved',\n    'comment' => 'Document manually verified by compliance.',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_feature_status(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_ocr_1\",\n  new_status: \"Approved\",\n  comment: \"Document manually verified by compliance.\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateFeatureStatusAsync(\"11111111-2222-3333-4444-555555555555\", \"feature_ocr_1\", new SessionsUpdateFeatureStatusParams\n{\n    NewStatus = \"Approved\",\n    Comment = \"Document manually verified by compliance.\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/update-aml-hit-status/": {
      "patch": {
        "summary": "Mettre à jour le statut d'examen d'une alerte AML",
        "description": "Définissez le statut d'examen d'un **résultat AML individuel** (une correspondance potentielle avec des sanctions / PEP / listes de surveillance / presse négative) renvoyé par le filtrage AML, sans modifier la décision globale de la session. Identifiez le résultat par son `hit_id` (le champ `id` d'une entrée dans le tableau `hits` du contrôle AML — voir la décision de la session). Un identifiant de résultat renvoyé sous l'ancien format est toujours accepté ; la réponse nomme toujours le résultat par son `id` actuel.\n\n`review_status` prend l'une des valeurs suivantes : `Unreviewed`, `Confirmed Match`, `False Positive` ou `Inconclusive`. Les décisions du réviseur sont conservées lors des mises à jour de la surveillance continue ; ainsi, un résultat marqué comme `False Positive` reste tel quel lorsque le fournisseur effectue un nouveau filtrage.\n\nUn appel réussi déclenche un webhook `data.updated` et ajoute une entrée d'activité (avec attribution de l'auteur) au journal d'examen de la session. Pour les workflows de type graphe comportant plusieurs contrôles AML, transmettez `node_id` pour cibler un contrôle spécifique.\n\nAuthentifiez-vous avec votre clé API (`x-api-key`) ou un en-tête d'autorisation utilisateur — l'un ou l'autre doit comporter le privilège `write:sessions`.",
        "operationId": "patch_v3_session_update_aml_hit_status",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_aml_hit_status",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB) — le service résout l'identifiant pour les deux types de session.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "in": "query",
            "name": "node_id",
            "required": false,
            "description": "ID de nœud du graphe de workflow. Requis uniquement lorsque la session comporte plusieurs contrôles AML (un par nœud) ; omettez-le pour les sessions avec un seul contrôle AML.",
            "schema": {
              "type": "string",
              "example": "feature_aml_1"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "hit_id",
                  "review_status"
                ],
                "properties": {
                  "hit_id": {
                    "type": "string",
                    "description": "L'`id` du résultat dans le tableau `hits` du contrôle AML (`hit_...`). Un identifiant de résultat renvoyé dans l'ancien format est toujours accepté.",
                    "example": "hit_7c1e9a40b2d35f86e0a4c912"
                  },
                  "review_status": {
                    "type": "string",
                    "description": "Le nouveau statut d'examen pour la correspondance.",
                    "enum": [
                      "Unreviewed",
                      "Confirmed Match",
                      "False Positive",
                      "Inconclusive"
                    ],
                    "example": "False Positive"
                  },
                  "node_id": {
                    "type": "string",
                    "description": "Identifiant de nœud de graphe optionnel. Utilisez-le (ici ou comme paramètre de requête) lorsque la session comporte plusieurs vérifications AML.",
                    "example": "feature_aml_1"
                  }
                }
              },
              "example": {
                "hit_id": "hit_7c1e9a40b2d35f86e0a4c912",
                "review_status": "False Positive"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Statut d'examen des correspondances mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "hit_id",
                    "review_status"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Toujours `Hit status updated successfully`."
                    },
                    "hit_id": {
                      "type": "string",
                      "description": "L'`id` du résultat mis à jour, tel que renvoyé par la décision de session, y compris lorsque la requête a désigné le résultat par un identifiant à l'ancien format."
                    },
                    "review_status": {
                      "type": "string",
                      "enum": [
                        "Unreviewed",
                        "Confirmed Match",
                        "False Positive",
                        "Inconclusive"
                      ],
                      "description": "Le statut d'examen désormais enregistré sur la correspondance."
                    }
                  }
                },
                "example": {
                  "message": "Hit status updated successfully",
                  "hit_id": "hit_7c1e9a40b2d35f86e0a4c912",
                  "review_status": "False Positive"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — `hit_id` vide ou `review_status` ne fait pas partie des valeurs autorisées.",
            "content": {
              "application/json": {
                "example": {
                  "review_status": [
                    "\"Maybe\" is not a valid choice."
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants ou autorisations insuffisantes. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "La clé API ne dispose pas de l'autorisation write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'a pas été trouvée, la session ne comporte aucune vérification AML (le cas échéant pour le `node_id` indiqué), ou aucun résultat ne correspond à `hit_id`.",
            "content": {
              "application/json": {
                "examples": {
                  "No AML Check": {
                    "summary": "La session n'a aucune vérification AML",
                    "value": {
                      "detail": "The session does not have an AML check."
                    }
                  },
                  "Hit Not Found": {
                    "summary": "hit_id inconnu",
                    "value": {
                      "detail": "Hit with ID 'hit_9d2e7f41c0a8b3e65d1f0c47' not found in the AML check."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/update-aml-hit-status/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"hit_id\": \"abc123\",\n    \"review_status\": \"False Positive\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_aml_hit_status(\n    \"11111111-2222-3333-4444-555555555555\",\n    hit_id=\"hit_7c1e9a40b2d35f86e0a4c912\",\n    review_status=\"False Positive\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateAmlHitStatus(\"11111111-2222-3333-4444-555555555555\", {\n  hit_id: \"hit_7c1e9a40b2d35f86e0a4c912\",\n  review_status: \"False Positive\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateAMLHitStatus(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsUpdateAMLHitStatusParams{\n\tHitID:        \"hit_7c1e9a40b2d35f86e0a4c912\",\n\tReviewStatus: \"False Positive\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsUpdateAmlHitStatusParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateAmlHitStatus(\"11111111-2222-3333-4444-555555555555\", SessionsUpdateAmlHitStatusParams.builder()\n        .hitId(\"hit_7c1e9a40b2d35f86e0a4c912\")\n        .reviewStatus(SessionsUpdateAmlHitStatusParams.ReviewStatus.of(\"False Positive\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateAmlHitStatus('11111111-2222-3333-4444-555555555555', [\n    'hit_id' => 'hit_7c1e9a40b2d35f86e0a4c912',\n    'review_status' => 'False Positive',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_aml_hit_status(\n  \"11111111-2222-3333-4444-555555555555\",\n  hit_id: \"hit_7c1e9a40b2d35f86e0a4c912\",\n  review_status: \"False Positive\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateAmlHitStatusAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsUpdateAmlHitStatusParams\n{\n    HitId = \"hit_7c1e9a40b2d35f86e0a4c912\",\n    ReviewStatus = \"False Positive\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/bulk-update-aml-hit-status/": {
      "patch": {
        "summary": "Mettre à jour en masse les statuts d'examen des correspondances AML",
        "description": "Mettre à jour le statut d'examen de **plusieurs résultats AML** en un seul appel. Fournissez `hit_updates`, une liste de paires `{ hit_id, review_status }`. `review_status` est l'une des valeurs : `Unreviewed`, `Confirmed Match`, `False Positive` ou `Inconclusive`.\n\nLa mise à jour est atomique : si un `hit_id` n'est pas trouvé dans la vérification AML, la requête renvoie `404` et aucun résultat n'est modifié. Un appel réussi déclenche un seul webhook `data.updated` et enregistre une entrée d'activité couvrant l'ensemble des modifications. Pour les workflows en graphe comportant plusieurs vérifications AML, transmettez `node_id` pour cibler une vérification spécifique.\n\nAuthentifiez-vous avec votre clé API (`x-api-key`) ou un en-tête d'autorisation utilisateur — l'un ou l'autre doit disposer du privilège `write:sessions`.",
        "operationId": "patch_v3_session_bulk_update_aml_hit_status",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "bulk_update_aml_hit_status",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB) — le service résout l'identifiant pour les deux types de session.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "in": "query",
            "name": "node_id",
            "required": false,
            "description": "ID de nœud du graphe de workflow. Requis uniquement lorsque la session comporte plusieurs contrôles AML (un par nœud) ; omettez-le pour les sessions avec un seul contrôle AML.",
            "schema": {
              "type": "string",
              "example": "feature_aml_1"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "hit_updates"
                ],
                "properties": {
                  "hit_updates": {
                    "type": "array",
                    "description": "Liste non vide de mises à jour de correspondances.",
                    "items": {
                      "type": "object",
                      "required": [
                        "hit_id",
                        "review_status"
                      ],
                      "properties": {
                        "hit_id": {
                          "type": "string",
                          "example": "hit_7c1e9a40b2d35f86e0a4c912",
                          "description": "L'`id` du résultat dans le tableau `hits` du contrôle AML (`hit_...`). Un identifiant de résultat renvoyé dans l'ancien format est toujours accepté."
                        },
                        "review_status": {
                          "type": "string",
                          "enum": [
                            "Unreviewed",
                            "Confirmed Match",
                            "False Positive",
                            "Inconclusive"
                          ],
                          "example": "Confirmed Match"
                        }
                      }
                    }
                  },
                  "node_id": {
                    "type": "string",
                    "description": "Identifiant de nœud de graphe optionnel. Utilisez-le (ici ou comme paramètre de requête) lorsque la session comporte plusieurs vérifications AML.",
                    "example": "feature_aml_1"
                  }
                }
              },
              "example": {
                "hit_updates": [
                  {
                    "hit_id": "hit_7c1e9a40b2d35f86e0a4c912",
                    "review_status": "Confirmed Match"
                  },
                  {
                    "hit_id": "hit_3b8f20d6a91c4e75f0b2d6a8",
                    "review_status": "False Positive"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tous les résultats mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "updated_hits"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "`Updated {n} hit(s) successfully`, où `n` est le nombre d'entrées dans `hit_updates`."
                    },
                    "updated_hits": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "L'`id` du résultat mentionné par chaque entrée de `hit_updates`, tel que renvoyé par la décision de session, dans l'ordre de la requête, y compris les résultats dont le statut n'a pas changé."
                    }
                  }
                },
                "example": {
                  "message": "Updated 2 hit(s) successfully",
                  "updated_hits": [
                    "hit_7c1e9a40b2d35f86e0a4c912",
                    "hit_3b8f20d6a91c4e75f0b2d6a8"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — `hit_updates` vide, ou une entrée ne comporte pas `hit_id` / `review_status` ou contient une valeur invalide.",
            "content": {
              "application/json": {
                "example": {
                  "hit_updates": [
                    "hit_updates cannot be empty"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants ou autorisations insuffisantes. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "La clé API ne dispose pas de l'autorisation write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'a pas été trouvée, la session ne comporte aucune vérification AML, ou un ou plusieurs `hit_id`s n'existent pas (aucune correspondance n'est modifiée dans ce cas).",
            "content": {
              "application/json": {
                "example": {
                  "detail": "Hits not found: hit_9d2e7f41c0a8b3e65d1f0c47"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/bulk-update-aml-hit-status/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"hit_updates\": [\n      { \"hit_id\": \"abc123\", \"review_status\": \"Confirmed Match\" },\n      { \"hit_id\": \"def456\", \"review_status\": \"False Positive\" }\n    ]\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.bulk_update_aml_hit_status(\n    \"11111111-2222-3333-4444-555555555555\",\n    hit_updates=[{\n        \"hit_id\": \"hit_7c1e9a40b2d35f86e0a4c912\",\n        \"review_status\": \"Confirmed Match\",\n    }, {\n        \"hit_id\": \"hit_3b8f20d6a91c4e75f0b2d6a8\",\n        \"review_status\": \"False Positive\",\n    }],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.bulkUpdateAmlHitStatus(\"11111111-2222-3333-4444-555555555555\", {\n  hit_updates: [{\n    hit_id: \"hit_7c1e9a40b2d35f86e0a4c912\",\n    review_status: \"Confirmed Match\",\n  }, {\n    hit_id: \"hit_3b8f20d6a91c4e75f0b2d6a8\",\n    review_status: \"False Positive\",\n  }],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.BulkUpdateAMLHitStatus(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsBulkUpdateAMLHitStatusParams{\n\tHitUpdates: []didit.SessionsBulkUpdateAMLHitStatusParamsHitUpdates{{\n\t\tHitID:        \"hit_7c1e9a40b2d35f86e0a4c912\",\n\t\tReviewStatus: \"Confirmed Match\",\n\t}, {\n\t\tHitID:        \"hit_3b8f20d6a91c4e75f0b2d6a8\",\n\t\tReviewStatus: \"False Positive\",\n\t}},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.SessionsBulkUpdateAmlHitStatusParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().bulkUpdateAmlHitStatus(\"11111111-2222-3333-4444-555555555555\", SessionsBulkUpdateAmlHitStatusParams.builder()\n        .hitUpdates(List.of(\n                SessionsBulkUpdateAmlHitStatusParams.HitUpdates.builder()\n                        .hitId(\"hit_7c1e9a40b2d35f86e0a4c912\")\n                        .reviewStatus(SessionsBulkUpdateAmlHitStatusParams.HitUpdates.ReviewStatus.of(\"Confirmed Match\"))\n                        .build(),\n                SessionsBulkUpdateAmlHitStatusParams.HitUpdates.builder()\n                        .hitId(\"hit_3b8f20d6a91c4e75f0b2d6a8\")\n                        .reviewStatus(SessionsBulkUpdateAmlHitStatusParams.HitUpdates.ReviewStatus.of(\"False Positive\"))\n                        .build()))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->bulkUpdateAmlHitStatus('11111111-2222-3333-4444-555555555555', [\n    'hit_updates' => [[\n        'hit_id' => 'hit_7c1e9a40b2d35f86e0a4c912',\n        'review_status' => 'Confirmed Match',\n    ], [\n        'hit_id' => 'hit_3b8f20d6a91c4e75f0b2d6a8',\n        'review_status' => 'False Positive',\n    ]],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.bulk_update_aml_hit_status(\n  \"11111111-2222-3333-4444-555555555555\",\n  hit_updates: [{\n    hit_id: \"hit_7c1e9a40b2d35f86e0a4c912\",\n    review_status: \"Confirmed Match\",\n  }, {\n    hit_id: \"hit_3b8f20d6a91c4e75f0b2d6a8\",\n    review_status: \"False Positive\",\n  }]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.BulkUpdateAmlHitStatusAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsBulkUpdateAmlHitStatusParams\n{\n    HitUpdates = new SessionsBulkUpdateAmlHitStatusParamsHitUpdates[]\n    {\n        new()\n        {\n            HitId = \"hit_7c1e9a40b2d35f86e0a4c912\",\n            ReviewStatus = \"Confirmed Match\",\n        },\n        new()\n        {\n            HitId = \"hit_3b8f20d6a91c4e75f0b2d6a8\",\n            ReviewStatus = \"False Positive\",\n        },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/update-poa-data/": {
      "patch": {
        "summary": "Mettre à jour les données de justificatif de domicile extraites du document POA lors d'une session de vérification",
        "description": "Corrigez les champs extraits du justificatif de domicile de l'utilisateur (facture de services publics, relevé bancaire ou autre justificatif d'adresse) une fois la vérification terminée : émetteur, dates, nom imprimé, adresse elle-même et coordonnées bancaires. Chaque champ du corps est facultatif : seules les clés que vous envoyez sont écrites, tout le reste demeure inchangé (sémantique `PATCH`).\n\nLa session doit appartenir à votre application et être dans l'état `Approved`, `Declined`, `In Review` ou `Kyc Expired`. Les sessions dans tout autre état (par exemple encore `In Progress`) renvoient `404` avec `\"No Session matches the given query.\"` — distinct du `\"Not found.\"` renvoyé pour un `sessionId` inconnu ou supprimé. La session doit également comporter un enregistrement POA : les sessions dont le workflow n'a jamais exécuté d'étape Justificatif de domicile renvoient `404` (`\"The session does not have a POA.\"`). Pour les workflows sous forme de graphe comportant plusieurs étapes POA, ciblez une étape spécifique à l'aide de `node_id` (paramètre de requête ou champ du corps) ; en cas d'omission, l'enregistrement POA le plus récent est modifié.\n\n`extra_fields` est fusionné clé par clé : neuf clés connues (`bank_iban`, `additional_names`, …) écrivent directement dans des colonnes POA dédiées, toute autre clé est conservée en tant qu'extra personnalisé, et `null` / `\"\"` supprime une clé. `poa_parsed_address` n'accepte que les sept clés documentées et recalcule `formatted_address` / `poa_formatted_address` après chaque modification. Si le champ de texte libre `poa_address` change, le serveur peut également le re-géocoder et actualiser l'adresse structurée (ignoré pour les sessions sandbox).\n\nContrairement à la variante KYC de cet endpoint, le [webhook](/fr/integration/webhooks) `data.updated` (déclencheur `manual_review`) ne se déclenche que si au moins une valeur stockée a **réellement changé** — renvoyer des valeurs identiques est une opération sans effet (no-op) silencieuse. Lorsque des valeurs changent, une entrée d'activité `POA_DATA_UPDATED` consignant les champs modifiés avec leurs valeurs précédentes et nouvelles est ajoutée aux `reviews` de la session, visible dans [Get Decision](#get-/v3/session/-sessionId-/decision/) et dans la chronologie d'activité de la console. Le statut et la décision de la session ne sont **pas** réévalués — utilisez [Update Status](#patch-/v3/session/-sessionId-/update-status/) pour modifier le résultat.\n\nAccepte une clé API ou un token d'utilisateur de console ; dans les deux cas, l'identifiant d'authentification doit disposer de l'autorisation `write:sessions`. Les échecs d'authentification et d'autorisation renvoient tous deux `403` — cette API ne répond jamais `401`. Notez que la recherche de session s'exécute avant les vérifications des identifiants, de sorte qu'un `sessionId` inconnu renvoie `404` même avec des identifiants manquants. Cet endpoint dispose d'une limite de débit dédiée de 10 requêtes par minute par clé API (les requêtes non valides comptent également) ; le budget d'écriture partagé de 300 requêtes par minute s'applique également.\n\nUn corps JSON vide `{}` est une opération sans effet : il renvoie `200` en renvoyant l'enregistrement POA actuel sans déclencher le webhook (`has_changes` reste faux).",
        "operationId": "patch_v3_session_update_poa_data",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_poa_data",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification des utilisateurs (KYC) dont vous corrigez l'enregistrement de justificatif de domicile associé.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud du graphe de workflow dont l'enregistrement POA doit être modifié, pour les workflows basés sur un graphe comportant plusieurs étapes de justificatif de domicile (également accepté en tant que champ `node_id` dans le corps). En cas d'omission, l'enregistrement POA le plus récent de la session est modifié. Si aucun POA n'existe pour le nœud indiqué, l'appel renvoie `404` (`\"The session does not have a POA for node '<node_id>'.\"`).",
            "schema": {
              "type": "string",
              "example": "feature_poa"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Tous les champs sont facultatifs : envoyez uniquement ce que vous souhaitez modifier.",
                "properties": {
                  "issuing_state": {
                    "type": "string",
                    "nullable": true,
                    "description": "Pays ayant délivré le document de justificatif de domicile, ISO 3166-1 alpha-3. Insensible à la casse (normalisé en majuscules) ; les codes invalides renvoient `400`.",
                    "example": "ESP"
                  },
                  "document_type": {
                    "type": "string",
                    "enum": [
                      "UTILITY_BILL",
                      "BANK_STATEMENT",
                      "GOVERNMENT_ISSUED_DOCUMENT",
                      "OTHER_POA_DOCUMENT",
                      "UNKNOWN"
                    ],
                    "description": "Catégorie de document de justificatif de domicile. Les valeurs sont en majuscules — les variantes en minuscules comme `utility_bill` renvoient un code `400`.",
                    "example": "UTILITY_BILL"
                  },
                  "document_language": {
                    "type": "string",
                    "maxLength": 50,
                    "nullable": true,
                    "description": "Langue du document, généralement un code ISO 639-1 (par exemple `es`). Texte libre — non validé en tant que code de langue.",
                    "example": "es"
                  },
                  "issuer": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Organisation ayant délivré le document (fournisseur de services publics, banque, organisme public).",
                    "example": "Energy Provider S.A."
                  },
                  "issue_date": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Date de délivrance du document de justificatif de domicile au format `YYYY-MM-DD`. Tout autre format renvoie `400`.",
                    "example": "2026-04-12"
                  },
                  "poa_address": {
                    "type": "string",
                    "nullable": true,
                    "description": "Adresse en texte libre telle qu'imprimée sur le document. Lorsque cette valeur change (sessions hors sandbox uniquement) et que l'adresse structurée est encore manquante ou incomplète, le serveur la géocode à nouveau en arrière-plan de la même requête et peut écraser `poa_parsed_address` / `poa_formatted_address` avec le résultat du géocodeur. Le nouveau géocodage nécessite également que `issuing_state` soit présent sur l'enregistrement POA.",
                    "example": "Avda de Madrid 34, 28013 Madrid"
                  },
                  "name_on_document": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Nom du destinataire tel qu'imprimé sur le document.",
                    "example": "Carmen Espanola"
                  },
                  "extra_fields": {
                    "type": "object",
                    "additionalProperties": true,
                    "nullable": true,
                    "description": "Champs supplémentaires spécifiques au document, fusionnés clé par clé. Neuf clés correspondent à des colonnes de justificatif de domicile dédiées : `bank_account_number`, `bank_iban`, `bank_sort_code`, `bank_routing_number`, `bank_swift_bic`, `bank_branch_name`, `bank_branch_address`, `document_phone_number` et `additional_names` (doit être une liste de chaînes ou `null`, sinon `400`). Toute autre clé est stockée sous forme de champ personnalisé supplémentaire. Sémantique par clé : une valeur définit la clé ; `null` ou `\"\"` la supprime. Doit être un objet JSON, sinon `400`."
                  },
                  "poa_parsed_address": {
                    "type": "object",
                    "nullable": true,
                    "description": "Adresse structurée. Seules ces clés imbriquées sont acceptées : `address_type`, `city`, `region`, `street_1`, `street_2`, `postal_code`, `country` — toute autre clé renvoie `400`. Sémantique par clé : une valeur définit la clé, `null` la supprime. `formatted_address` (ainsi que `poa_formatted_address` au niveau supérieur) est recalculée côté serveur en concaténant `street_1`, `street_2`, `city`, `region`, `postal_code` et `country` — vous ne pouvez pas la définir directement.",
                    "properties": {
                      "address_type": {
                        "type": "string",
                        "nullable": true,
                        "description": "Classification d'adresse en texte libre (par ex. `home`)."
                      },
                      "city": {
                        "type": "string",
                        "nullable": true,
                        "example": "Madrid"
                      },
                      "region": {
                        "type": "string",
                        "nullable": true,
                        "description": "État / province / communauté autonome."
                      },
                      "street_1": {
                        "type": "string",
                        "nullable": true,
                        "example": "Avda de Madrid 34"
                      },
                      "street_2": {
                        "type": "string",
                        "nullable": true
                      },
                      "postal_code": {
                        "type": "string",
                        "nullable": true,
                        "example": "28013"
                      },
                      "country": {
                        "type": "string",
                        "nullable": true,
                        "description": "Code pays ISO 3166-1 alpha-2. Les entrées en minuscules sont normalisées en majuscules ; les codes alpha-3 sont rejetés avec une erreur `400`.",
                        "example": "ES"
                      }
                    }
                  }
                }
              },
              "examples": {
                "Correct issuer and address": {
                  "summary": "Corriger la classification du document, l'émetteur et l'adresse structurée",
                  "value": {
                    "issuing_state": "ESP",
                    "document_type": "BANK_STATEMENT",
                    "issuer": "Banco Example S.A.",
                    "issue_date": "2026-05-02",
                    "name_on_document": "Carmen Espanola",
                    "poa_address": "Avda de Madrid 34, 28013 Madrid",
                    "extra_fields": {
                      "bank_iban": "ES9121000418450200051332",
                      "additional_names": [
                        "Carmen E. Espanola"
                      ]
                    },
                    "poa_parsed_address": {
                      "street_1": "Avda de Madrid 34",
                      "city": "Madrid",
                      "postal_code": "28013",
                      "country": "ES"
                    }
                  }
                },
                "Remove a banking detail": {
                  "summary": "Supprimer une clé de champ supplémentaire, conserver le reste",
                  "value": {
                    "extra_fields": {
                      "bank_iban": null
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Données du justificatif de domicile mises à jour. Renvoie l'**enregistrement POA actuel complet** (chaque champ modifiable avec sa valeur stockée, plus le dictionnaire `extra_fields` complet, `poa_parsed_address` et `poa_formatted_address`) — pas seulement les champs que vous avez soumis. Le webhook `data.updated` ne se déclenche que si au moins une valeur a réellement changé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "issuing_state": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pays ayant délivré le document de justificatif de domicile, ISO 3166-1 alpha-3. Insensible à la casse (normalisé en majuscules) ; les codes invalides renvoient `400`.",
                      "example": "ESP"
                    },
                    "document_type": {
                      "type": "string",
                      "enum": [
                        "UTILITY_BILL",
                        "BANK_STATEMENT",
                        "GOVERNMENT_ISSUED_DOCUMENT",
                        "OTHER_POA_DOCUMENT",
                        "UNKNOWN"
                      ],
                      "description": "Catégorie de document de justificatif de domicile. Les valeurs sont en majuscules — les variantes en minuscules comme `utility_bill` renvoient un code `400`.",
                      "example": "UTILITY_BILL"
                    },
                    "document_language": {
                      "type": "string",
                      "maxLength": 50,
                      "nullable": true,
                      "description": "Langue du document, généralement un code ISO 639-1 (par exemple `es`). Texte libre — non validé en tant que code de langue.",
                      "example": "es"
                    },
                    "issuer": {
                      "type": "string",
                      "maxLength": 255,
                      "nullable": true,
                      "description": "Organisation ayant délivré le document (fournisseur de services publics, banque, organisme public).",
                      "example": "Energy Provider S.A."
                    },
                    "issue_date": {
                      "type": "string",
                      "format": "date",
                      "nullable": true,
                      "description": "Date de délivrance du document de justificatif de domicile au format `YYYY-MM-DD`. Tout autre format renvoie `400`.",
                      "example": "2026-04-12"
                    },
                    "poa_address": {
                      "type": "string",
                      "nullable": true,
                      "description": "Adresse en texte libre telle qu'imprimée sur le document. Lorsque cette valeur change (sessions hors sandbox uniquement) et que l'adresse structurée est encore manquante ou incomplète, le serveur la géocode à nouveau en arrière-plan de la même requête et peut écraser `poa_parsed_address` / `poa_formatted_address` avec le résultat du géocodeur.",
                      "example": "Avda de Madrid 34, 28013 Madrid"
                    },
                    "name_on_document": {
                      "type": "string",
                      "maxLength": 255,
                      "nullable": true,
                      "description": "Nom du destinataire tel qu'imprimé sur le document.",
                      "example": "Carmen Espanola"
                    },
                    "extra_fields": {
                      "type": "object",
                      "additionalProperties": true,
                      "nullable": true,
                      "description": "Toujours présentes dans la réponse : les neuf clés connues (avec `null` pour celles non définies, `additional_names` valant par défaut `[]`) ainsi que toutes les clés personnalisées précédemment stockées."
                    },
                    "poa_parsed_address": {
                      "type": "object",
                      "nullable": true,
                      "description": "Adresse structurée actuelle, ou `null` si aucune n'existe. Comprend le champ recalculé `formatted_address` ainsi que les sept clés modifiables. Renvoyée telle qu'elle est stockée — après un géocodage côté serveur, elle peut contenir des clés de suivi (par ex. `raw_results`) en plus des clés modifiables.",
                      "properties": {
                        "address_type": {
                          "type": "string",
                          "nullable": true,
                          "description": "Classification d'adresse en texte libre (par ex. `home`)."
                        },
                        "city": {
                          "type": "string",
                          "nullable": true,
                          "example": "Madrid"
                        },
                        "region": {
                          "type": "string",
                          "nullable": true,
                          "description": "État / province / communauté autonome."
                        },
                        "street_1": {
                          "type": "string",
                          "nullable": true,
                          "example": "Avda de Madrid 34"
                        },
                        "street_2": {
                          "type": "string",
                          "nullable": true
                        },
                        "postal_code": {
                          "type": "string",
                          "nullable": true,
                          "example": "28013"
                        },
                        "country": {
                          "type": "string",
                          "nullable": true,
                          "description": "Code pays ISO 3166-1 alpha-2. Les entrées en minuscules sont normalisées en majuscules ; les codes alpha-3 sont rejetés avec une erreur `400`.",
                          "example": "ES"
                        },
                        "formatted_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Forme assemblée et lisible par l'humain de l'adresse structurée. Recalculée côté serveur après chaque modification de `poa_parsed_address`.",
                          "example": "Avda de Madrid 34, Madrid, 28013, ES"
                        }
                      }
                    },
                    "poa_formatted_address": {
                      "type": "string",
                      "nullable": true,
                      "description": "Copie de premier niveau du champ `formatted_address` recalculé, maintenue synchronisée lorsque l'adresse structurée change.",
                      "example": "Avda de Madrid 34, Madrid, 28013, ES"
                    }
                  }
                },
                "examples": {
                  "Updated POA": {
                    "summary": "Dossier POA complet après la correction",
                    "value": {
                      "issuing_state": "ESP",
                      "document_type": "BANK_STATEMENT",
                      "document_language": "es",
                      "issuer": "Banco Example S.A.",
                      "issue_date": "2026-05-02",
                      "poa_address": "Avda de Madrid 34, 28013 Madrid",
                      "name_on_document": "Carmen Espanola",
                      "extra_fields": {
                        "bank_account_number": null,
                        "bank_iban": "ES9121000418450200051332",
                        "bank_sort_code": null,
                        "bank_routing_number": null,
                        "bank_swift_bic": null,
                        "bank_branch_name": null,
                        "bank_branch_address": null,
                        "document_phone_number": null,
                        "additional_names": [
                          "Carmen E. Espanola"
                        ]
                      },
                      "poa_parsed_address": {
                        "city": "Madrid",
                        "street_1": "Avda de Madrid 34",
                        "postal_code": "28013",
                        "country": "ES",
                        "formatted_address": "Avda de Madrid 34, Madrid, 28013, ES"
                      },
                      "poa_formatted_address": "Avda de Madrid 34, Madrid, 28013, ES"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les erreurs de champ sont renvoyées sous la forme `{\"<field>\": [\"<message>\"]}` ; les erreurs sur les clés imbriquées de `poa_parsed_address` / `extra_fields` utilisent un objet : `{\"extra_fields\": {\"<key>\": \"<message>\"}}`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid document type": {
                    "summary": "L'énumération est en majuscules — les variantes en minuscules sont rejetées",
                    "value": {
                      "document_type": [
                        "\"utility_bill\" is not a valid choice."
                      ]
                    }
                  },
                  "Invalid issuing state": {
                    "summary": "issuing_state n'est pas au format ISO 3166-1 alpha-3",
                    "value": {
                      "issuing_state": [
                        "Invalid ISO 3166-1 alpha-3 country code for issuing_state."
                      ]
                    }
                  },
                  "additional_names not a list": {
                    "summary": "additional_names accepte une liste de chaînes de caractères ou null",
                    "value": {
                      "extra_fields": {
                        "additional_names": "Must be a list or null."
                      }
                    }
                  },
                  "Unsupported poa_parsed_address key": {
                    "summary": "Seules les sept clés documentées sont autorisées",
                    "value": {
                      "poa_parsed_address": {
                        "zipcode": "Unsupported key. Allowed keys: address_type, city, region, street_1, street_2, postal_code, country"
                      }
                    }
                  },
                  "Bad date format": {
                    "summary": "Les dates doivent être au format YYYY-MM-DD",
                    "value": {
                      "issue_date": [
                        "Date has wrong format. Use one of these formats instead: YYYY-MM-DD."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants ou autorisations insuffisantes. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'identifiant ne dispose pas de write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Session inconnue, session dans un état non modifiable, ou aucun enregistrement de justificatif de domicile à modifier. Chaque cas dispose d'un message `detail` distinct (voir exemples). La recherche de la session inconnue s'exécute avant les vérifications des identifiants.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID dans votre application (ou elle a été supprimée)",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Wrong session state": {
                    "summary": "La session existe mais n'est pas Approved / Declined / In Review / Kyc Expired",
                    "value": {
                      "detail": "No Session matches the given query."
                    }
                  },
                  "No POA record": {
                    "summary": "Le workflow n'a jamais exécuté d'étape Justificatif de domicile",
                    "value": {
                      "detail": "The session does not have a POA."
                    }
                  },
                  "No POA for node": {
                    "summary": "node_id fourni mais aucun POA n'existe pour celui-ci",
                    "value": {
                      "detail": "The session does not have a POA for node 'feature_missing'."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dédiée dépassée — 10 mises à jour de données POA par minute et par clé API (les requêtes rejetées sont décomptées du quota). Le quota partagé d'écriture de 300/min peut également se déclencher avec son propre message. Examinez `Retry-After` et les en-têtes de réponse `X-RateLimit-*` avant de réessayer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget de mise à jour POA épuisé",
                    "value": {
                      "detail": "Session POA data update rate limit exceeded. You can make up to 10 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH \\\n  https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/update-poa-data/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"issuing_state\": \"ESP\",\n    \"document_type\": \"BANK_STATEMENT\",\n    \"issuer\": \"Banco Example S.A.\",\n    \"issue_date\": \"2026-05-02\",\n    \"name_on_document\": \"Carmen Espanola\",\n    \"poa_address\": \"Avda de Madrid 34, 28013 Madrid\",\n    \"extra_fields\": {\n      \"bank_iban\": \"ES9121000418450200051332\"\n    },\n    \"poa_parsed_address\": {\n      \"city\": \"Madrid\",\n      \"postal_code\": \"28013\",\n      \"country\": \"ES\"\n    }\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_poa_data(\n    \"11111111-2222-3333-4444-555555555555\",\n    issuing_state=\"ESP\",\n    document_type=\"BANK_STATEMENT\",\n    issuer=\"Banco Example S.A.\",\n    issue_date=\"2026-05-02\",\n    poa_address=\"Avda de Madrid 34, 28013 Madrid\",\n    name_on_document=\"Carmen Espanola\",\n    extra_fields={\"bank_iban\": \"ES9121000418450200051332\", \"additional_names\": [\"Carmen E. Espanola\"]},\n    poa_parsed_address={\n        \"city\": \"Madrid\",\n        \"street_1\": \"Avda de Madrid 34\",\n        \"postal_code\": \"28013\",\n        \"country\": \"ES\",\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updatePoaData(\"11111111-2222-3333-4444-555555555555\", {\n  issuing_state: \"ESP\",\n  document_type: \"BANK_STATEMENT\",\n  issuer: \"Banco Example S.A.\",\n  issue_date: \"2026-05-02\",\n  poa_address: \"Avda de Madrid 34, 28013 Madrid\",\n  name_on_document: \"Carmen Espanola\",\n  extra_fields: { bank_iban: \"ES9121000418450200051332\", additional_names: [\"Carmen E. Espanola\"] },\n  poa_parsed_address: {\n    city: \"Madrid\",\n    street_1: \"Avda de Madrid 34\",\n    postal_code: \"28013\",\n    country: \"ES\",\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdatePOAData(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsUpdatePOADataParams{\n\tIssuingState:   didit.String(\"ESP\"),\n\tDocumentType:   didit.Some(didit.SessionsUpdatePOADataParamsDocumentType(\"BANK_STATEMENT\")),\n\tIssuer:         didit.String(\"Banco Example S.A.\"),\n\tIssueDate:      didit.String(\"2026-05-02\"),\n\tPOAAddress:     didit.String(\"Avda de Madrid 34, 28013 Madrid\"),\n\tNameOnDocument: didit.String(\"Carmen Espanola\"),\n\tExtraFields:    didit.Some(map[string]any{\"bank_iban\": \"ES9121000418450200051332\", \"additional_names\": []any{\"Carmen E. Espanola\"}}),\n\tPOAParsedAddress: didit.Some(didit.SessionsUpdatePOADataParamsPOAParsedAddress{\n\t\tCity:       didit.String(\"Madrid\"),\n\t\tStreet1:    didit.String(\"Avda de Madrid 34\"),\n\t\tPostalCode: didit.String(\"28013\"),\n\t\tCountry:    didit.String(\"ES\"),\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.LocalDate;\nimport java.util.List;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.SessionsUpdatePoaDataParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updatePoaData(\"11111111-2222-3333-4444-555555555555\", SessionsUpdatePoaDataParams.builder()\n        .issuingState(\"ESP\")\n        .documentType(SessionsUpdatePoaDataParams.DocumentType.of(\"BANK_STATEMENT\"))\n        .issuer(\"Banco Example S.A.\")\n        .issueDate(LocalDate.parse(\"2026-05-02\"))\n        .poaAddress(\"Avda de Madrid 34, 28013 Madrid\")\n        .nameOnDocument(\"Carmen Espanola\")\n        .extraFields(Map.of(\"bank_iban\", \"ES9121000418450200051332\", \"additional_names\", List.of(\"Carmen E. Espanola\")))\n        .poaParsedAddress(SessionsUpdatePoaDataParams.PoaParsedAddress.builder()\n                .city(\"Madrid\")\n                .street1(\"Avda de Madrid 34\")\n                .postalCode(\"28013\")\n                .country(\"ES\")\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updatePoaData('11111111-2222-3333-4444-555555555555', [\n    'issuing_state' => 'ESP',\n    'document_type' => 'BANK_STATEMENT',\n    'issuer' => 'Banco Example S.A.',\n    'issue_date' => '2026-05-02',\n    'poa_address' => 'Avda de Madrid 34, 28013 Madrid',\n    'name_on_document' => 'Carmen Espanola',\n    'extra_fields' => ['bank_iban' => 'ES9121000418450200051332', 'additional_names' => ['Carmen E. Espanola']],\n    'poa_parsed_address' => [\n        'city' => 'Madrid',\n        'street_1' => 'Avda de Madrid 34',\n        'postal_code' => '28013',\n        'country' => 'ES',\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_poa_data(\n  \"11111111-2222-3333-4444-555555555555\",\n  issuing_state: \"ESP\",\n  document_type: \"BANK_STATEMENT\",\n  issuer: \"Banco Example S.A.\",\n  issue_date: \"2026-05-02\",\n  poa_address: \"Avda de Madrid 34, 28013 Madrid\",\n  name_on_document: \"Carmen Espanola\",\n  extra_fields: { bank_iban: \"ES9121000418450200051332\", additional_names: [\"Carmen E. Espanola\"] },\n  poa_parsed_address: {\n    city: \"Madrid\",\n    street_1: \"Avda de Madrid 34\",\n    postal_code: \"28013\",\n    country: \"ES\",\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdatePoaDataAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsUpdatePoaDataParams\n{\n    IssuingState = \"ESP\",\n    DocumentType = new SessionsUpdatePoaDataParamsDocumentType(\"BANK_STATEMENT\"),\n    Issuer = \"Banco Example S.A.\",\n    IssueDate = \"2026-05-02\",\n    PoaAddress = \"Avda de Madrid 34, 28013 Madrid\",\n    NameOnDocument = \"Carmen Espanola\",\n    ExtraFields = new Dictionary<string, object> { [\"bank_iban\"] = \"ES9121000418450200051332\", [\"additional_names\"] = new object[] { \"Carmen E. Espanola\" } },\n    PoaParsedAddress = new SessionsUpdatePoaDataParamsPoaParsedAddress\n    {\n        City = \"Madrid\",\n        Street1 = \"Avda de Madrid 34\",\n        PostalCode = \"28013\",\n        Country = \"ES\",\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/kyb/{companyUuid}/update-data/": {
      "patch": {
        "summary": "Mettre à jour les données d'entreprise extraites du registre sur une session de Vérification d'entreprise (KYB)",
        "description": "Corrige les données d'entreprise extraites du registre dans une session de Vérification d'entreprise (KYB) — nom de l'entreprise, numéro d'immatriculation, adresses, statut, coordonnées — identifiée par `companyUuid`. Les appelants types sont un analyste de conformité rectifiant une mauvaise lecture du registre, ou votre back-office synchronisant des données d'entreprise corrigées. Chaque champ du corps est optionnel (sémantique `PATCH`) ; un corps JSON vide (`{}`) est une opération sans effet qui renvoie simplement l'enregistrement actuel de l'entreprise.\n\nLes modifications sont écrites à deux endroits à la fois : les champs disposant d'une colonne canonique pour l'entreprise (nom, numéro d'immatriculation, pays, date de constitution, identifiant fiscal, type, statuts, champs de capital (`registered_capital`, `registered_capital_amount`, `registered_capital_currency`), noms alternatifs, nature de l'activité, site web, e-mail, téléphone, LEI, emplacement et `legal_address` → `registered_address`) mettent à jour cette colonne, et **chaque** clé soumise est également fusionnée dans l'instantané `registry_data` (dates sous forme de chaînes ISO) afin que la vue « extrait du registre » reflète la correction. Les champs sans colonne — `region`, `registration_date`, `dissolution_date`, `control_scheme` — sont enregistrés uniquement dans `registry_data`. `user_provided_data` (ce que l'utilisateur final a confirmé dans le flux hébergé) n'est jamais modifié, et `last_console_edit_at` est horodaté à chaque PATCH non vide.\n\nContrairement aux endpoints de mise à jour KYC/POA, il n'y a **aucun blocage lié au statut de la session** : l'entreprise peut être modifiée à tout moment du cycle de vie de la session d'entreprise. L'entreprise doit appartenir à la session indiquée dans le chemin (`404` avec `\"KYB company does not belong to the given session.\"` sinon) ainsi qu'à votre application. Chaque PATCH non vide déclenche le [webhook](/fr/integration/webhooks) `data.updated` sur la session d'entreprise (déclencheur `console_registry_edit`) — même lorsque les valeurs soumises sont identiques à celles stockées. Le statut et la décision de la session ne sont **pas** réévalués, et aucune entrée d'examen ou d'audit n'est enregistrée.\n\nAccepte une clé API ou un token d'utilisateur de console ; dans les deux cas, les identifiants doivent disposer de l'autorisation `write:businesses`. Les échecs d'authentification et d'autorisation renvoient tous deux `403` — cette API ne répond jamais `401`. Notez que la recherche de la session s'exécute avant la vérification des identifiants, de sorte qu'un `sessionId` inconnu renvoie `404` même avec des identifiants manquants. Le quota partagé d'écriture de 300 requêtes par minute et par clé API s'applique.\n\nPour les sessions de Vérification des utilisateurs, l'équivalent KYC est `PATCH /v3/session/{sessionId}/update-data/` ; pour modifier la décision de la session elle-même, utilisez `PATCH /v3/session/{sessionId}/update-status/`.",
        "operationId": "patch_v3_session_kyb_company_update_data",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_kyb_company_data",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session parente de Vérification d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "companyUuid",
            "in": "path",
            "required": true,
            "description": "UUID de l'enregistrement de l'entreprise à mettre à jour (`registry_checks[].company.uuid` sur la décision de la session d'entreprise). Doit appartenir à la session référencée par `sessionId`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "88888888-9999-aaaa-bbbb-cccccccccccc"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Tous les champs sont facultatifs — envoyez uniquement ce que vous souhaitez modifier. Les champs fournis mettent à jour les colonnes canoniques de l'entreprise (lorsqu'il en existe une) et sont fusionnés dans l'instantané de `registry_data`.",
                "properties": {
                  "company_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Raison sociale de l'entreprise. Écrite dans la colonne canonique et l'instantané du registre.",
                    "example": "Docs Probe Corp"
                  },
                  "registration_number": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Numéro d'immatriculation officiel auprès du registre des sociétés.",
                    "example": "DPC-001"
                  },
                  "country_code": {
                    "type": "string",
                    "maxLength": 2,
                    "description": "Pays de constitution, ISO 3166-1 alpha-2. Insensible à la casse (`us` est stocké sous la forme `US`). Les codes alpha-3 échouent à la limite de 2 caractères avec `400`.",
                    "example": "US"
                  },
                  "region": {
                    "type": "string",
                    "maxLength": 10,
                    "nullable": true,
                    "description": "Balise de subdivision / région lorsque le registre en possède une (par exemple un État américain). Stockée uniquement dans l'instantané du registre — elle ne possède pas de colonne canonique."
                  },
                  "incorporation_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Date de constitution au format `YYYY-MM-DD`. Facultatif comme tous les autres champs — le `PATCH` est partiel. Tout autre format de date renvoie `400`.",
                    "example": "2015-04-12"
                  },
                  "registration_date": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Date d'immatriculation lorsque le registre la distingue de la constitution. Enregistrée uniquement dans l'instantané du registre."
                  },
                  "dissolution_date": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Date de dissolution pour les entreprises qui ne sont plus actives. Enregistrée uniquement dans l'instantané du registre."
                  },
                  "tax_number": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Identifiant fiscal."
                  },
                  "legal_address": {
                    "type": "string",
                    "description": "Adresse légale / adresse enregistrée. Fait l'objet d'un alias côté serveur vers la colonne canonique `registered_address` — la réponse la renvoie sous `registered_address`, tandis que l'instantané du registre conserve la clé `legal_address` que vous avez envoyée.",
                    "example": "1 Example Plaza, Wilmington, DE 19801"
                  },
                  "company_type": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Type d'entité juridique (par exemple `Limited Liability Company`, `PLC`, `GmbH`).",
                    "example": "Limited Liability Company"
                  },
                  "registry_status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "dissolved",
                      "deregistered",
                      "see full details",
                      "authorised",
                      "appointed representative",
                      "unauthorised",
                      "inactive",
                      "no longer authorised",
                      "closed",
                      "struck off"
                    ],
                    "nullable": true,
                    "description": "Statut de l'entreprise indiqué par le registre. En minuscules, certaines valeurs contiennent des espaces (par ex. `struck off`, `no longer authorised`). Toute autre valeur renvoie `400`.",
                    "example": "active"
                  },
                  "verification_status": {
                    "type": "string",
                    "enum": [
                      "verified",
                      "failed",
                      "unknown"
                    ],
                    "nullable": true,
                    "description": "Résultat de la vérification du registre. Toute autre valeur renvoie `400`.",
                    "example": "verified"
                  },
                  "alternative_names": {
                    "type": "string",
                    "description": "Noms commerciaux, anciens noms légaux, noms d'emprunt (texte libre)."
                  },
                  "nature_of_business": {
                    "type": "string",
                    "description": "Courte description de l'activité de l'entreprise.",
                    "example": "Software development"
                  },
                  "registered_capital": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Capital social lisible par l'utilisateur (par exemple `USD 50000`). Utilisez `registered_capital_amount` + `registered_capital_currency` pour des valeurs structurées, ou ce champ pour du texte libre.",
                    "example": "USD 50000"
                  },
                  "registered_capital_amount": {
                    "type": "number",
                    "format": "double",
                    "nullable": true,
                    "description": "Montant numérique du capital social (jusqu'à 20 chiffres, 2 décimales). Définit la colonne `registered_capital_amount` et est répercuté dans `registry_data` sous forme de chaîne décimale ; la réponse le renvoie sous forme de chaîne décimale (par ex. `\"1500000.50\"`)."
                  },
                  "registered_capital_currency": {
                    "type": "string",
                    "maxLength": 3,
                    "nullable": true,
                    "description": "Code de devise ISO 4217 pour `registered_capital_amount`. Insensible à la casse (`usd` est stocké sous la forme `USD`) ; les valeurs qui ne comportent pas exactement 3 lettres renvoient `400` avec le message ISO 4217. Définit la colonne canonique `registered_capital_currency` et est répliqué dans `registry_data`.",
                    "example": "USD"
                  },
                  "website": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Site web de l'entreprise. Les domaines nus sont acceptés et normalisés avec un préfixe `https://` (`docsprobe.example.com` est stocké sous la forme `https://docsprobe.example.com`) ; les valeurs qui échouent toujours à la validation de l'URL renvoient `400`.",
                    "example": "https://docsprobe.example.com"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "E-mail de contact enregistré auprès du registre.",
                    "example": "legal@docsprobe.example.com"
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 50,
                    "description": "Téléphone de contact. Doit correspondre à `+`, chiffres, espaces, tirets, points ou parenthèses, avec un total de 7 à 15 chiffres — sinon `400`.",
                    "example": "+1 302 555 0143"
                  },
                  "legal_entity_identifier": {
                    "type": "string",
                    "maxLength": 50,
                    "description": "LEI, lorsque l'entreprise en possède un."
                  },
                  "location_of_registration": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Ville / subdivision du registre officiel."
                  },
                  "vat_number": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Numéro de TVA de l'UE. Fusionné uniquement dans l'instantané de `registry_data` — le modifier ici ne réexécute pas la validation de la TVA et de l'identifiant fiscal, de sorte que `vat_validation_status` et les autres champs de résultat `vat_*` restent inchangés."
                  },
                  "control_scheme": {
                    "type": "string",
                    "description": "Régime de contrôle / gouvernance lorsque le registre l'expose. Stocké uniquement dans l'instantané du registre."
                  }
                }
              },
              "examples": {
                "Correct registry data": {
                  "summary": "Corriger les champs extraits du registre des sociétés de l'entreprise",
                  "value": {
                    "company_name": "Docs Probe Corp",
                    "registration_number": "DPC-001",
                    "country_code": "US",
                    "incorporation_date": "2015-04-12",
                    "company_type": "Limited Liability Company",
                    "legal_address": "1 Example Plaza, Wilmington, DE 19801",
                    "registry_status": "active",
                    "verification_status": "verified",
                    "website": "docsprobe.example.com",
                    "email": "legal@docsprobe.example.com",
                    "phone": "+1 302 555 0143",
                    "registered_capital": "USD 50000",
                    "nature_of_business": "Software development"
                  }
                },
                "Single field": {
                  "summary": "Seules les clés que vous envoyez sont écrites",
                  "value": {
                    "registry_status": "dissolved"
                  }
                },
                "No-op": {
                  "summary": "Un corps vide renvoie l'enregistrement actuel sans déclencher le webhook",
                  "value": {}
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Données de l'entreprise mises à jour (ou renvoyées inchangées pour un corps vide). Renvoie l'enregistrement complet de l'entreprise KYB — au même format que `registry_checks[].company` sur la décision de la session d'entreprise. Notez que `legal_address` est retournée sous forme de `registered_address`. `registered_capital_amount`/`registered_capital_currency` renseignent leurs colonnes canoniques et sont dupliqués dans `registry_data`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Dossier d'entreprise KYB complet — de même structure que l'objet `company` au sein de `registry_checks[]` sur la décision de session d'entreprise.",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de l'enregistrement de l'entreprise (le paramètre de chemin `companyUuid`)."
                    },
                    "node_id": {
                      "type": "string",
                      "nullable": true,
                      "description": "Nœud du graphe de workflow auquel appartient cet enregistrement d'entreprise, lorsque le workflow est basé sur un graphe."
                    },
                    "status": {
                      "type": "string",
                      "description": "Statut du cycle de vie de la fonctionnalité pour la vérification du registre (par ex. `Not Finished`, `Approved`, `Declined`, `In Review`)."
                    },
                    "registry_status": {
                      "type": "string",
                      "nullable": true,
                      "description": "Statut de l'entreprise indiqué par le registre (par ex. `active`, `dissolved`, `struck off`)."
                    },
                    "data_resolved": {
                      "type": "boolean",
                      "description": "`true` lorsque les données de l'entreprise sont complètes — toujours `true` pour les entreprises saisies manuellement ; pour les entreprises issues d'un registre, `true` une fois la récupération auprès du registre terminée."
                    },
                    "company_name": {
                      "type": "string",
                      "nullable": true
                    },
                    "registration_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "country_code": {
                      "type": "string",
                      "nullable": true,
                      "description": "Code pays ISO 3166-1 alpha-2 du pays de constitution."
                    },
                    "region": {
                      "type": "string",
                      "nullable": true
                    },
                    "company_type": {
                      "type": "string",
                      "nullable": true
                    },
                    "incorporation_date": {
                      "type": "string",
                      "format": "date",
                      "nullable": true
                    },
                    "registered_address": {
                      "type": "string",
                      "nullable": true,
                      "description": "Adresse canonique enregistrée — mise à jour lorsque vous envoyez `legal_address`."
                    },
                    "tax_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "risk_level": {
                      "type": "string",
                      "nullable": true
                    },
                    "verification_status": {
                      "type": "string",
                      "nullable": true,
                      "description": "`verified`, `failed` ou `unknown`."
                    },
                    "is_from_registry": {
                      "type": "boolean",
                      "description": "`true` lorsque l'entreprise a été préremplie à partir d'une recherche dans un registre plutôt que saisie manuellement."
                    },
                    "fetch_status": {
                      "type": "string",
                      "nullable": true,
                      "description": "Cycle de vie de la récupération auprès du registre pour les entreprises issues d'un registre (`pending` / `resolved`) ; `null` pour les saisies manuelles."
                    },
                    "alternative_names": {
                      "type": "string",
                      "nullable": true,
                      "description": "Dénominations commerciales, alternatives, anciennes ou dans la langue d'origine de l'entreprise sous forme de texte, lorsqu'elles sont déclarées."
                    },
                    "nature_of_business": {
                      "type": "string",
                      "nullable": true
                    },
                    "registered_capital": {
                      "type": "string",
                      "nullable": true
                    },
                    "registered_capital_amount": {
                      "type": "string",
                      "nullable": true,
                      "description": "Colonne canonique. Renvoyée sous forme de chaîne décimale (par ex. `\"2750000.00\"`)."
                    },
                    "registered_capital_currency": {
                      "type": "string",
                      "nullable": true,
                      "description": "Colonne canonique. Définie par le flux de registre ou par des modifications effectuées via la console ou l'API avec cet endpoint."
                    },
                    "website": {
                      "type": "string",
                      "nullable": true
                    },
                    "email": {
                      "type": "string",
                      "nullable": true
                    },
                    "phone": {
                      "type": "string",
                      "nullable": true
                    },
                    "legal_entity_identifier": {
                      "type": "string",
                      "nullable": true
                    },
                    "location_of_registration": {
                      "type": "string",
                      "nullable": true
                    },
                    "vat_number": {
                      "type": "string",
                      "nullable": true,
                      "description": "Numéro de TVA de l'UE, lorsqu'il est recueilli lors de l'étape de registre hébergée ou modifié ultérieurement."
                    },
                    "vat_validation_status": {
                      "type": "string",
                      "enum": [
                        "valid",
                        "invalid",
                        "format_valid",
                        "invalid_format",
                        "could_not_validate",
                        "not_applicable"
                      ],
                      "description": "Résultat de la validation du numéro de TVA ou, s'il n'y en a pas, du `tax_number`, lors de la soumission au registre. `valid` / `invalid` : déterminé par le registre officiel du pays (VIES UE, Norvège, Suisse, Brésil, Colombie, Costa Rica, Équateur, Paraguay ; Pologne également par son registre national de TVA). `format_valid` / `invalid_format` : déterminé par les règles de format et de chiffre de contrôle du pays lorsqu'aucun registre ne peut être interrogé. `could_not_validate` : le registre était indisponible. `not_applicable` : pas de numéro, un pays sans registre ni règles, ou une session sandbox."
                    },
                    "vat_validated_number": {
                      "type": "string",
                      "nullable": true,
                      "description": "Le numéro qui a été vérifié, tel que la source le connaît (par exemple le numéro de TVA dérivé d'un SIREN français ou d'un RSIN néerlandais). `null` si aucune vérification n'a été effectuée."
                    },
                    "vat_validation_source": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "eu_vies",
                        "pl_vat_white_list",
                        "no_brreg",
                        "ch_uid_register",
                        "br_receita_federal",
                        "co_rues",
                        "cr_hacienda",
                        "ec_sri",
                        "py_dnit",
                        "format_rules",
                        null
                      ],
                      "description": "La source ayant déterminé `vat_validation_status` : un registre officiel ou `format_rules`. Vaut `null` si aucune vérification n'a été exécutée."
                    },
                    "vat_validated_name": {
                      "type": "string",
                      "nullable": true,
                      "description": "Nom enregistré auprès de la source ayant validé le numéro, lorsqu'elle en communique un. Défini uniquement lorsque le statut est `valid`."
                    },
                    "vat_validated_address": {
                      "type": "string",
                      "nullable": true,
                      "description": "Adresse enregistrée auprès de la source ayant validé le numéro, lorsqu'elle en divulgue une. Renseigné uniquement lorsque le statut est `valid`."
                    },
                    "vat_checked_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Horodatage de la vérification. `null` si aucune vérification n'a été exécutée."
                    },
                    "financial_summary": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true
                    },
                    "officers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "description": "Dirigeants / responsables rattachés à l'entreprise, y compris l'avancement du KYC par personne."
                    },
                    "beneficial_owners": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "description": "Bénéficiaires effectifs rattachés à l'entreprise, y compris l'avancement du KYC par personne."
                    },
                    "addresses": {
                      "type": "array",
                      "nullable": true,
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "description": "Détails de l'adresse du registre, lorsque le registre en a renvoyé."
                    },
                    "industries": {
                      "type": "array",
                      "nullable": true,
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "description": "Classification sectorielle du registre, lorsqu'elle est disponible."
                    },
                    "accounts": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Dates de dépôt au registre, lorsqu'elles sont disponibles. Les déclarations annuelles et les assemblées générales utilisent last_annual_return_date et last_agm_date ; elles sont distinctes des comptes financiers."
                    },
                    "registry_data": {
                      "$ref": "#/components/schemas/KYBRegistryData"
                    },
                    "user_provided_data": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Ce que l'utilisateur final a saisi lors de l'étape hébergée de confirmation auprès du registre. Jamais modifié par cet endpoint."
                    },
                    "confirmed_by_user_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Date et heure auxquelles l'utilisateur final a confirmé les données de l'entreprise dans le flux hébergé."
                    },
                    "last_console_edit_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Inscrit sur chaque PATCH non vide réussi, afin que les interfaces puissent afficher le contexte \"modifié par l'opérateur\"."
                    },
                    "is_editable": {
                      "type": "boolean",
                      "description": "`true` tant que l'utilisateur final peut encore modifier les données issues du registre dans le flux hébergé (issues du registre et pas encore confirmées)."
                    }
                  }
                },
                "examples": {
                  "Updated company": {
                    "summary": "Dossier complet de l'entreprise après la correction",
                    "value": {
                      "uuid": "6b9479f5-6769-46c8-baf1-df63bbbc5f8c",
                      "node_id": null,
                      "status": "Not Finished",
                      "registry_status": "active",
                      "data_resolved": true,
                      "company_name": "Docs Probe Corp",
                      "registration_number": "DPC-001",
                      "country_code": "US",
                      "region": null,
                      "company_type": "Limited Liability Company",
                      "incorporation_date": "2015-04-12",
                      "registered_address": "1 Example Plaza, Wilmington, DE 19801",
                      "tax_number": null,
                      "risk_level": null,
                      "verification_status": "verified",
                      "is_from_registry": false,
                      "fetch_status": null,
                      "alternative_names": null,
                      "nature_of_business": "Software development",
                      "registered_capital": "USD 50000",
                      "registered_capital_amount": null,
                      "registered_capital_currency": "USD",
                      "website": "https://docsprobe.example.com",
                      "email": "legal@docsprobe.example.com",
                      "phone": "+1 302 555 0143",
                      "legal_entity_identifier": null,
                      "location_of_registration": null,
                      "financial_summary": null,
                      "officers": [],
                      "beneficial_owners": [],
                      "addresses": null,
                      "industries": null,
                      "accounts": null,
                      "registry_data": {
                        "company_name": "Docs Probe Corp",
                        "registration_number": "DPC-001",
                        "country_code": "US",
                        "incorporation_date": "2015-04-12",
                        "legal_address": "1 Example Plaza, Wilmington, DE 19801",
                        "company_type": "Limited Liability Company",
                        "registry_status": "active",
                        "verification_status": "verified",
                        "nature_of_business": "Software development",
                        "registered_capital": "USD 50000",
                        "registered_capital_currency": "USD",
                        "website": "https://docsprobe.example.com",
                        "email": "legal@docsprobe.example.com",
                        "phone": "+1 302 555 0143"
                      },
                      "user_provided_data": null,
                      "confirmed_by_user_at": null,
                      "last_console_edit_at": "2026-06-12T00:02:34.276061Z",
                      "is_editable": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les erreurs de champ sont renvoyées sous la forme `{\"<field>\": [\"<message>\"]}`. Les vérifications de longueur maximale s'exécutent avant les vérifications de format, ainsi `country_code: \"USA\"` signale la limite de 2 caractères plutôt que le message ISO.",
            "content": {
              "application/json": {
                "examples": {
                  "Alpha-3 country code": {
                    "summary": "country_code doit être au format alpha-2 — la vérification de la longueur se déclenche en premier",
                    "value": {
                      "country_code": [
                        "Ensure this field has no more than 2 characters."
                      ]
                    }
                  },
                  "Non-alphabetic country code": {
                    "summary": "2 caractères mais pas des lettres",
                    "value": {
                      "country_code": [
                        "country_code must be a 2-letter ISO 3166-1 alpha-2 code."
                      ]
                    }
                  },
                  "Invalid currency": {
                    "summary": "3 caractères mais pas un code ISO 4217",
                    "value": {
                      "registered_capital_currency": [
                        "Currency must be a 3-letter ISO 4217 code (e.g. USD, EUR, GBP)."
                      ]
                    }
                  },
                  "Invalid phone": {
                    "summary": "Le téléphone ne respecte pas le contrôle de format / nombre de chiffres",
                    "value": {
                      "phone": [
                        "Invalid phone number format."
                      ]
                    }
                  },
                  "Invalid registry status": {
                    "summary": "registry_status n'appartient pas à l'énumération",
                    "value": {
                      "registry_status": [
                        "\"liquidated\" is not a valid choice."
                      ]
                    }
                  },
                  "Invalid email": {
                    "summary": "Adresse e-mail mal formée",
                    "value": {
                      "email": [
                        "Enter a valid email address."
                      ]
                    }
                  },
                  "Invalid website": {
                    "summary": "La valeur ne passe pas la validation de l'URL même après la normalisation https://",
                    "value": {
                      "website": [
                        "Enter a valid URL."
                      ]
                    }
                  },
                  "Bad date format": {
                    "summary": "Les dates doivent être au format YYYY-MM-DD",
                    "value": {
                      "incorporation_date": [
                        "Date has wrong format. Use one of these formats instead: YYYY-MM-DD."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants ou autorisations insuffisantes. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'identifiant ne dispose pas de write:businesses",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Session inconnue, entreprise inconnue ou entreprise appartenant à une session différente. Chaque cas dispose d'un message `detail` distinct (voir exemples). La recherche de la session inconnue est exécutée avant les vérifications des identifiants.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID dans votre application (ou elle a été supprimée)",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Unknown company": {
                    "summary": "Aucune entreprise avec cet UUID dans votre application",
                    "value": {
                      "detail": "No KYBCompany matches the given query."
                    }
                  },
                  "Company / session mismatch": {
                    "summary": "companyUuid existe mais appartient à une autre session",
                    "value": {
                      "detail": "KYB company does not belong to the given session."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit d'écriture partagée dépassée (300 requêtes POST/PATCH/DELETE par minute et par clé API). Examinez `Retry-After` et les en-têtes de réponse `X-RateLimit-*` avant de réessayer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget d'écriture épuisé",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH \\\n  https://verification.didit.me/v3/session/33333333-4444-5555-6666-777777777777/kyb/88888888-9999-aaaa-bbbb-cccccccccccc/update-data/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"company_name\": \"Docs Probe Corp\",\n    \"registration_number\": \"DPC-001\",\n    \"country_code\": \"US\",\n    \"incorporation_date\": \"2015-04-12\",\n    \"company_type\": \"Limited Liability Company\",\n    \"legal_address\": \"1 Example Plaza, Wilmington, DE 19801\",\n    \"registry_status\": \"active\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_kyb_company_data(\n    \"33333333-4444-5555-6666-777777777777\",\n    \"88888888-9999-aaaa-bbbb-cccccccccccc\",\n    company_name=\"Docs Probe Corp\",\n    registration_number=\"DPC-001\",\n    country_code=\"US\",\n    incorporation_date=\"2015-04-12\",\n    legal_address=\"1 Example Plaza, Wilmington, DE 19801\",\n    company_type=\"Limited Liability Company\",\n    registry_status=\"active\",\n    verification_status=\"verified\",\n    nature_of_business=\"Software development\",\n    registered_capital=\"USD 50000\",\n    website=\"docsprobe.example.com\",\n    email=\"legal@docsprobe.example.com\",\n    phone=\"+1 302 555 0143\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateKybCompanyData(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"88888888-9999-aaaa-bbbb-cccccccccccc\",\n  {\n    company_name: \"Docs Probe Corp\",\n    registration_number: \"DPC-001\",\n    country_code: \"US\",\n    incorporation_date: \"2015-04-12\",\n    legal_address: \"1 Example Plaza, Wilmington, DE 19801\",\n    company_type: \"Limited Liability Company\",\n    registry_status: \"active\",\n    verification_status: \"verified\",\n    nature_of_business: \"Software development\",\n    registered_capital: \"USD 50000\",\n    website: \"docsprobe.example.com\",\n    email: \"legal@docsprobe.example.com\",\n    phone: \"+1 302 555 0143\",\n  },\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateKYBCompanyData(ctx, \"33333333-4444-5555-6666-777777777777\", \"88888888-9999-aaaa-bbbb-cccccccccccc\", didit.SessionsUpdateKYBCompanyDataParams{\n\tCompanyName:        didit.String(\"Docs Probe Corp\"),\n\tRegistrationNumber: didit.String(\"DPC-001\"),\n\tCountryCode:        didit.String(\"US\"),\n\tIncorporationDate:  didit.String(\"2015-04-12\"),\n\tLegalAddress:       didit.String(\"1 Example Plaza, Wilmington, DE 19801\"),\n\tCompanyType:        didit.String(\"Limited Liability Company\"),\n\tRegistryStatus:     didit.Some(didit.SessionsUpdateKYBCompanyDataParamsRegistryStatus(\"active\")),\n\tVerificationStatus: didit.Some(didit.SessionsUpdateKYBCompanyDataParamsVerificationStatus(\"verified\")),\n\tNatureOfBusiness:   didit.String(\"Software development\"),\n\tRegisteredCapital:  didit.String(\"USD 50000\"),\n\tWebsite:            didit.String(\"docsprobe.example.com\"),\n\tEmail:              didit.String(\"legal@docsprobe.example.com\"),\n\tPhone:              didit.String(\"+1 302 555 0143\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.LocalDate;\nimport me.didit.Didit;\nimport me.didit.types.SessionsUpdateKybCompanyDataParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateKybCompanyData(\"33333333-4444-5555-6666-777777777777\", \"88888888-9999-aaaa-bbbb-cccccccccccc\", SessionsUpdateKybCompanyDataParams.builder()\n        .companyName(\"Docs Probe Corp\")\n        .registrationNumber(\"DPC-001\")\n        .countryCode(\"US\")\n        .incorporationDate(LocalDate.parse(\"2015-04-12\"))\n        .legalAddress(\"1 Example Plaza, Wilmington, DE 19801\")\n        .companyType(\"Limited Liability Company\")\n        .registryStatus(SessionsUpdateKybCompanyDataParams.RegistryStatus.of(\"active\"))\n        .verificationStatus(SessionsUpdateKybCompanyDataParams.VerificationStatus.of(\"verified\"))\n        .natureOfBusiness(\"Software development\")\n        .registeredCapital(\"USD 50000\")\n        .website(\"docsprobe.example.com\")\n        .email(\"legal@docsprobe.example.com\")\n        .phone(\"+1 302 555 0143\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateKybCompanyData('33333333-4444-5555-6666-777777777777', '88888888-9999-aaaa-bbbb-cccccccccccc', [\n    'company_name' => 'Docs Probe Corp',\n    'registration_number' => 'DPC-001',\n    'country_code' => 'US',\n    'incorporation_date' => '2015-04-12',\n    'legal_address' => '1 Example Plaza, Wilmington, DE 19801',\n    'company_type' => 'Limited Liability Company',\n    'registry_status' => 'active',\n    'verification_status' => 'verified',\n    'nature_of_business' => 'Software development',\n    'registered_capital' => 'USD 50000',\n    'website' => 'docsprobe.example.com',\n    'email' => 'legal@docsprobe.example.com',\n    'phone' => '+1 302 555 0143',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_kyb_company_data(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"88888888-9999-aaaa-bbbb-cccccccccccc\",\n  company_name: \"Docs Probe Corp\",\n  registration_number: \"DPC-001\",\n  country_code: \"US\",\n  incorporation_date: \"2015-04-12\",\n  legal_address: \"1 Example Plaza, Wilmington, DE 19801\",\n  company_type: \"Limited Liability Company\",\n  registry_status: \"active\",\n  verification_status: \"verified\",\n  nature_of_business: \"Software development\",\n  registered_capital: \"USD 50000\",\n  website: \"docsprobe.example.com\",\n  email: \"legal@docsprobe.example.com\",\n  phone: \"+1 302 555 0143\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateKybCompanyDataAsync(\"33333333-4444-5555-6666-777777777777\", \"88888888-9999-aaaa-bbbb-cccccccccccc\", new SessionsUpdateKybCompanyDataParams\n{\n    CompanyName = \"Docs Probe Corp\",\n    RegistrationNumber = \"DPC-001\",\n    CountryCode = \"US\",\n    IncorporationDate = \"2015-04-12\",\n    LegalAddress = \"1 Example Plaza, Wilmington, DE 19801\",\n    CompanyType = \"Limited Liability Company\",\n    RegistryStatus = new SessionsUpdateKybCompanyDataParamsRegistryStatus(\"active\"),\n    VerificationStatus = new SessionsUpdateKybCompanyDataParamsVerificationStatus(\"verified\"),\n    NatureOfBusiness = \"Software development\",\n    RegisteredCapital = \"USD 50000\",\n    Website = \"docsprobe.example.com\",\n    Email = \"legal@docsprobe.example.com\",\n    Phone = \"+1 302 555 0143\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/kyb/parties/{partyUuid}/": {
      "patch": {
        "summary": "Ignorer (ou exiger à nouveau) une personne clé d'une session de Vérification d'entreprise (KYB)",
        "description": "Exemptez une partie prenante des personnes clés de la vérification, ou réintégrez-la dans le périmètre. Il s'agit de la solution de secours pour l'opérateur lorsqu'une partie prenante ne peut jamais terminer sa propre vérification - le plus souvent parce que la session KYC individuelle transmise à un UBO ou à un dirigeant a été supprimée, ce qui fige le statut de cette session enfant et laisse le KYB bloqué sur `Awaiting User` sans plus rien pour le faire évoluer.\n\nDéfinir `is_skipped: true` retire la partie prenante de l'agrégation des personnes clés et recalcule immédiatement le `KYBKeyPeopleCheck` ainsi que le statut de la session parente, afin que la session d'entreprise puisse être finalisée puis approuvée ou refusée. Envoyer `is_skipped: false` réintègre la partie prenante dans le périmètre et la vérification se remet à l'attendre.\n\nContrairement au saut proposé au candidat dans l'écran hébergé des personnes clés, cet endpoint n'est **pas** conditionné par le paramètre `allow_skip` du rôle : cet indicateur limite ce que le candidat peut décider, et non ce que votre analyste peut outrepasser. `requires_verification` est délibérément conservé intact, de sorte qu'une partie prenante faisant l'objet d'une dérogation affiche `requires_verification: true` **et** `is_skipped: true`, et l'enregistrement continue d'indiquer ce que les règles exigeaient.\n\nLa partie prenante doit appartenir à la session figurant dans le chemin (`404` avec `\"Party does not belong to the given session.\"` dans le cas contraire) et à votre application. Un PATCH modifiant réellement l'indicateur déclenche le [webhook](/fr/integration/webhooks) `data.updated` sur la session d'entreprise avec le déclencheur `console_key_people_skip` ; un PATCH définissant l'indicateur à sa valeur actuelle est sans effet et renvoie simplement la partie prenante.\n\nAccepte une clé API ou un token d'utilisateur de la console ; dans les deux cas, le moyen d'authentification doit disposer de l'autorisation `write:businesses`.",
        "operationId": "patch_v3_session_kyb_party_update",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_kyb_party",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session parente de Vérification d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "partyUuid",
            "in": "path",
            "required": true,
            "description": "UUID de la partie « personnes clés » à mettre à jour (`key_people_checks[].submitted.parties[].uuid` sur la décision de la session d'entreprise). Doit appartenir à la session référencée par `sessionId`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "is_skipped"
                ],
                "properties": {
                  "is_skipped": {
                    "type": "boolean",
                    "description": "`true` dispense la partie de vérification afin que le contrôle des personnes clés puisse se conclure sans elle ; `false` la réintègre dans le périmètre.",
                    "example": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Partie mise à jour (ou renvoyée sans modification lorsque l'indicateur avait déjà cette valeur). Renvoie la partie - sous la même forme qu'une entrée de `key_people_checks[].submitted.parties[]` dans la décision de la session d'entreprise.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Enregistrement de partie des personnes clés - même format qu'une entrée de `key_people_checks[].submitted.parties[]` sur la décision de session d'entreprise.",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de la partie."
                    },
                    "entity_type": {
                      "type": "string",
                      "enum": [
                        "person",
                        "company"
                      ],
                      "description": "Indique si la partie est un particulier ou une entreprise."
                    },
                    "name": {
                      "type": "string",
                      "description": "Nom d'affichage de la partie."
                    },
                    "is_skipped": {
                      "type": "boolean",
                      "description": "Indique si la partie est exemptée de vérification."
                    },
                    "requires_verification": {
                      "type": "boolean",
                      "description": "Ce que les règles de rôles et de seuils demandaient. Laissé intact par cet endpoint."
                    },
                    "kyc_session_status": {
                      "type": "string",
                      "nullable": true,
                      "description": "Statut de la session KYC individuelle associée, figé au moment de la suppression lorsque la session a été supprimée."
                    },
                    "kyc_session_url": {
                      "type": "string",
                      "nullable": true,
                      "description": "Lien vers la session KYC individuelle associée. `null` lorsqu'il n'y en a pas ou lorsqu'elle a été supprimée."
                    },
                    "kyc_session_deleted": {
                      "type": "boolean",
                      "description": "La session de KYC individuel liée a été supprimée, elle ne pourra donc jamais aboutir."
                    },
                    "kyb_sub_session_deleted": {
                      "type": "boolean",
                      "description": "Équivalent pour personne morale de `kyc_session_deleted`."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation sur le corps de la requête. `is_skipped` est le seul champ lu par cet endpoint, et il est obligatoire. Les erreurs de champ sont renvoyées sous la forme `{\"<field>\": [\"<message>\"]}`. La validation du corps s'exécute *après* la recherche de la partie, donc un champ `is_skipped` mal formé envoyé à une partie qui n'existe pas renvoie `404`, et non `400`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing is_skipped": {
                    "summary": "Corps vide, ou un corps qui omet `is_skipped`",
                    "value": {
                      "is_skipped": [
                        "This field is required."
                      ]
                    }
                  },
                  "Non-boolean is_skipped": {
                    "summary": "La valeur n'est pas un booléen — `\"maybe\"`, `2`, `[]`. Les booléens ainsi que `\"true\"`/`\"false\"`, `1`/`0` et `\"yes\"`/`\"no\"` sont tous acceptés",
                    "value": {
                      "is_skipped": [
                        "Must be a valid boolean."
                      ]
                    }
                  },
                  "Null is_skipped": {
                    "summary": "`is_skipped` est présent mais vaut `null`",
                    "value": {
                      "is_skipped": [
                        "This field may not be null."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants ou autorisations insuffisantes. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'identifiant ne dispose pas de write:businesses",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Partie inconnue, ou partie appartenant à une session différente. Chaque cas dispose d'un message `detail` distinct (voir exemples). Les vérifications des identifiants et des autorisations sont exécutées avant la recherche de la partie, un appel non autorisé renvoie donc `403` plutôt que `404`. Il n'y a pas de recherche de session distincte : un `sessionId` inconnu associé à l'une de vos parties renvoie le message d'incompatibilité.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown party": {
                    "summary": "Aucune partie avec cet UUID dans votre application",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Party / session mismatch": {
                    "summary": "partyUuid existe mais est rattaché à une autre session",
                    "value": {
                      "detail": "Party does not belong to the given session."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit d'écriture partagée dépassée (300 requêtes POST/PATCH/DELETE par minute et par clé API). Examinez `Retry-After` et les en-têtes de réponse `X-RateLimit-*` avant de réessayer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget d'écriture épuisé",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_kyb_party(\n    \"33333333-4444-5555-6666-777777777777\",\n    \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\",\n    is_skipped=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateKybParty(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\",\n  {\n    is_skipped: true,\n  },\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateKYBParty(ctx, \"33333333-4444-5555-6666-777777777777\", \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\", didit.SessionsUpdateKYBPartyParams{\n\tIsSkipped: true,\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsUpdateKybPartyParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateKybParty(\"33333333-4444-5555-6666-777777777777\", \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\", SessionsUpdateKybPartyParams.builder()\n        .isSkipped(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateKybParty('33333333-4444-5555-6666-777777777777', '0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41', [\n    'is_skipped' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_kyb_party(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\",\n  is_skipped: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateKybPartyAsync(\"33333333-4444-5555-6666-777777777777\", \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\", new SessionsUpdateKybPartyParams\n{\n    IsSkipped = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/travel-rule/settings/": {
      "get": {
        "summary": "Obtenir les paramètres Travel Rule",
        "description": "Lire les paramètres Travel Rule et le profil VASP de l'application. Crée automatiquement une ligne de paramètres par défaut (désactivée) et un profil vide lors de la première lecture.",
        "operationId": "getTravelRuleSettings",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "retrieve_settings",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/settings/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.retrieve_settings()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.retrieveSettings();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.RetrieveSettings(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().retrieveSettings();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->retrieveSettings();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.retrieve_settings\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.RetrieveSettingsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Paramètres actuels de la Travel Rule et profil VASP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleSettingsDetail"
                },
                "examples": {
                  "Disabled (default)": {
                    "value": {
                      "is_enabled": false,
                      "jurisdiction": "EU",
                      "name_matching_strictness": "DEFAULT",
                      "confirmation_timeout_hours": 48,
                      "timeout_outcome": "HOLD",
                      "threshold_amount": "0.00",
                      "inbound_auto_accept": true,
                      "allow_self_declaration": true,
                      "allow_screenshot_proof": true,
                      "auto_wallet_verification": true,
                      "vasp_attribution_enabled": true,
                      "legal_name": "",
                      "lei": "",
                      "compliance_email": "",
                      "is_discoverable": true,
                      "counterparty_screening_enabled": false,
                      "sunrise_policy": "",
                      "sunrise_jurisdictions": [
                        "CO",
                        "KH",
                        "VN"
                      ],
                      "non_responsive_policy": "",
                      "travel_address": "",
                      "disabled_networks": [],
                      "networks": {
                        "gtr": {
                          "rail": "GTR",
                          "mode": "unavailable",
                          "state": "didit_onboarding",
                          "reason": "didit_membership_not_live",
                          "platform_available": false,
                          "connected": false,
                          "participant": null,
                          "vasps_reachable": 0,
                          "routed_30d": 0
                        },
                        "trust": {
                          "rail": "TRUST",
                          "mode": "unavailable",
                          "state": "unavailable",
                          "reason": "own_membership_only",
                          "platform_available": false,
                          "connected": false,
                          "participant": null,
                          "vasps_reachable": 0,
                          "routed_30d": 0
                        },
                        "verifyvasp": {
                          "rail": "VERIFYVASP",
                          "mode": "unavailable",
                          "state": "didit_onboarding",
                          "reason": "didit_membership_not_live",
                          "platform_available": false,
                          "connected": false,
                          "participant": null,
                          "vasps_reachable": 0,
                          "routed_30d": 0
                        },
                        "sygna": {
                          "rail": "SYGNA",
                          "mode": "unavailable",
                          "state": "didit_onboarding",
                          "reason": "didit_membership_not_live",
                          "platform_available": false,
                          "connected": false,
                          "participant": null,
                          "vasps_reachable": 0,
                          "routed_30d": 0
                        }
                      },
                      "didit_network": {
                        "listed": false,
                        "missing": [
                          "travel_rule_off",
                          "legal_name_missing",
                          "compliance_email_missing"
                        ],
                        "compliance_email_confirmed": false
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Mettre à jour les paramètres Travel Rule",
        "description": "Crée ou met à jour les paramètres Travel Rule et le profil VASP de l'application. Mise à jour partielle — n'envoyez que les champs que vous souhaitez modifier. Définir `is_enabled: true` nécessite un `legal_name` non vide (déjà enregistré ou inclus dans la même requête), sinon renvoie 400.",
        "operationId": "updateTravelRuleSettings",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "update_settings",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleSettingsUpdate"
              },
              "example": {
                "is_enabled": true,
                "legal_name": "Origin CASP SL",
                "jurisdiction": "EU",
                "name_matching_strictness": "DEFAULT",
                "confirmation_timeout_hours": 48,
                "timeout_outcome": "HOLD",
                "is_discoverable": true
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PUT https://verification.didit.me/v3/travel-rule/settings/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"is_enabled\": true, \"legal_name\": \"Origin CASP SL\", \"jurisdiction\": \"EU\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.update_settings(\n    is_enabled=True,\n    legal_name=\"Origin CASP SL\",\n    jurisdiction=\"EU\",\n    name_matching_strictness=\"DEFAULT\",\n    confirmation_timeout_hours=48,\n    timeout_outcome=\"HOLD\",\n    is_discoverable=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.updateSettings({\n  is_enabled: true,\n  legal_name: \"Origin CASP SL\",\n  jurisdiction: \"EU\",\n  name_matching_strictness: \"DEFAULT\",\n  confirmation_timeout_hours: 48,\n  timeout_outcome: \"HOLD\",\n  is_discoverable: true,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.UpdateSettings(ctx, didit.TravelRuleSettingsUpdate{\n\tIsEnabled:                didit.Bool(true),\n\tLegalName:                didit.String(\"Origin CASP SL\"),\n\tJurisdiction:             didit.String(\"EU\"),\n\tNameMatchingStrictness:   didit.Some(didit.TravelRuleSettingsUpdateNameMatchingStrictness(\"DEFAULT\")),\n\tConfirmationTimeoutHours: didit.Int(48),\n\tTimeoutOutcome:           didit.Some(didit.TravelRuleSettingsUpdateTimeoutOutcome(\"HOLD\")),\n\tIsDiscoverable:           didit.Bool(true),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleSettingsUpdate;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().updateSettings(TravelRuleSettingsUpdate.builder()\n        .isEnabled(true)\n        .legalName(\"Origin CASP SL\")\n        .jurisdiction(\"EU\")\n        .nameMatchingStrictness(TravelRuleSettingsUpdate.NameMatchingStrictness.of(\"DEFAULT\"))\n        .confirmationTimeoutHours(48L)\n        .timeoutOutcome(TravelRuleSettingsUpdate.TimeoutOutcome.of(\"HOLD\"))\n        .isDiscoverable(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->updateSettings([\n    'is_enabled' => true,\n    'legal_name' => 'Origin CASP SL',\n    'jurisdiction' => 'EU',\n    'name_matching_strictness' => 'DEFAULT',\n    'confirmation_timeout_hours' => 48,\n    'timeout_outcome' => 'HOLD',\n    'is_discoverable' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.update_settings(\n  is_enabled: true,\n  legal_name: \"Origin CASP SL\",\n  jurisdiction: \"EU\",\n  name_matching_strictness: \"DEFAULT\",\n  confirmation_timeout_hours: 48,\n  timeout_outcome: \"HOLD\",\n  is_discoverable: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.UpdateSettingsAsync(new TravelRuleSettingsUpdate\n{\n    IsEnabled = true,\n    LegalName = \"Origin CASP SL\",\n    Jurisdiction = \"EU\",\n    NameMatchingStrictness = new TravelRuleSettingsUpdateNameMatchingStrictness(\"DEFAULT\"),\n    ConfirmationTimeoutHours = 48,\n    TimeoutOutcome = new TravelRuleSettingsUpdateTimeoutOutcome(\"HOLD\"),\n    IsDiscoverable = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Paramètres et profil mis à jour, sous la même forme que le GET.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleSettingsDetail"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation, par exemple activation sans legal_name, sunrise_policy ou non_responsive_policy autre que HOLD, REJECT, PROCEED ou vide, champ inconnu dans `matching_rules`, ou choix de `data_sharing_fields` ne pouvant pas respecter les obligations de donneur d'ordre du régime de votre juridiction (les erreurs sont indexées par type d'entité sous `data_sharing_fields`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "legal_name": [
                    "legal_name is required to enable travel rule."
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/settings/compliance-email/confirmation/": {
      "post": {
        "summary": "Envoyez l'e-mail de confirmation de conformité",
        "description": "Envoie un lien de confirmation à usage unique par e-mail au compliance_email de votre profil VASP. Ouvrir le lien et cliquer sur son bouton de confirmation confirme l'adresse, ce dont le réseau Didit a besoin avant de lister votre profil. Une nouvelle requête remplace le lien précédent ; le lien cesse de fonctionner lorsque l'e-mail de conformité change. Un e-mail par minute et par adresse.",
        "operationId": "sendTravelRuleComplianceEmailConfirmation",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "send_compliance_email_confirmation",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/settings/compliance-email/confirmation/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.send_compliance_email_confirmation()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.sendComplianceEmailConfirmation();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.SendComplianceEmailConfirmation(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().sendComplianceEmailConfirmation();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->sendComplianceEmailConfirmation();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.send_compliance_email_confirmation\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.SendComplianceEmailConfirmationAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "202": {
            "description": "L'e-mail de confirmation a été envoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sent_to": {
                      "type": "string",
                      "format": "email"
                    }
                  }
                },
                "example": {
                  "sent_to": "compliance@your-vasp.example"
                }
              }
            }
          },
          "400": {
            "description": "Aucun e-mail de conformité n'est défini, ou il est déjà confirmé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "No compliance email": {
                    "value": {
                      "compliance_email": [
                        "Set a compliance email before confirming it."
                      ]
                    }
                  },
                  "Already confirmed": {
                    "value": {
                      "compliance_email": [
                        "This compliance email is already confirmed."
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Une confirmation a été envoyée à cette adresse il y a moins d'une minute."
          },
          "503": {
            "description": "L'e-mail n'a pas pu être envoyé. Rien n'a changé ; réessayez dans un instant."
          }
        }
      }
    },
    "/v3/travel-rule/wallet-addresses/": {
      "get": {
        "summary": "Lister les entrées du carnet d'adresses de portefeuilles",
        "description": "Liste paginée du carnet d'adresses de portefeuilles Travel Rule de votre application, de la plus récente à la plus ancienne.",
        "operationId": "listTravelRuleWalletAddresses",
        "x-didit-sdk": {
          "resource": "travel_rule.wallet_addresses",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/wallet-addresses/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.travel_rule.wallet_addresses.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.travelRule.walletAddresses.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.TravelRule.WalletAddresses.ListAutoPaging(ctx, didit.TravelRuleWalletAddressesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.travelRule().walletAddresses().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->travelRule->walletAddresses->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.travel_rule.wallet_addresses.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.TravelRule.WalletAddresses.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Entrées du carnet d'adresses de portefeuilles paginées.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WalletAddressEntry"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Enregistrer une adresse de portefeuille",
        "description": "Ajoutez une entrée à votre carnet d'adresses de portefeuilles Travel Rule afin que les transferts entrants du rail INTERNAL puissent être mis en correspondance avec celle-ci.",
        "operationId": "createTravelRuleWalletAddress",
        "x-didit-sdk": {
          "resource": "travel_rule.wallet_addresses",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WalletAddressEntryCreate"
              },
              "example": {
                "address": "0xBeneficiaryWallet01",
                "chain": "ETH",
                "holder_name": "Ana Diaz",
                "holder_vendor_data": "user-042",
                "self_declared": true
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/wallet-addresses/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"address\": \"0xBeneficiaryWallet01\", \"chain\": \"ETH\", \"holder_name\": \"Ana Diaz\", \"self_declared\": true}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.wallet_addresses.create(\n    address=\"0xBeneficiaryWallet01\",\n    chain=\"ETH\",\n    holder_vendor_data=\"user-042\",\n    holder_name=\"Ana Diaz\",\n    self_declared=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.walletAddresses.create({\n  address: \"0xBeneficiaryWallet01\",\n  chain: \"ETH\",\n  holder_vendor_data: \"user-042\",\n  holder_name: \"Ana Diaz\",\n  self_declared: true,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.WalletAddresses.Create(ctx, didit.WalletAddressEntryCreate{\n\tAddress:          \"0xBeneficiaryWallet01\",\n\tChain:            didit.String(\"ETH\"),\n\tHolderVendorData: didit.String(\"user-042\"),\n\tHolderName:       didit.String(\"Ana Diaz\"),\n\tSelfDeclared:     didit.Bool(true),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.WalletAddressEntryCreate;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().walletAddresses().create(WalletAddressEntryCreate.builder()\n        .address(\"0xBeneficiaryWallet01\")\n        .chain(\"ETH\")\n        .holderVendorData(\"user-042\")\n        .holderName(\"Ana Diaz\")\n        .selfDeclared(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->walletAddresses->create([\n    'address' => '0xBeneficiaryWallet01',\n    'chain' => 'ETH',\n    'holder_vendor_data' => 'user-042',\n    'holder_name' => 'Ana Diaz',\n    'self_declared' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.wallet_addresses.create(\n  address: \"0xBeneficiaryWallet01\",\n  chain: \"ETH\",\n  holder_vendor_data: \"user-042\",\n  holder_name: \"Ana Diaz\",\n  self_declared: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.WalletAddresses.CreateAsync(new WalletAddressEntryCreate\n{\n    Address = \"0xBeneficiaryWallet01\",\n    Chain = \"ETH\",\n    HolderVendorData = \"user-042\",\n    HolderName = \"Ana Diaz\",\n    SelfDeclared = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "L'entrée créée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletAddressEntry"
                }
              }
            }
          },
          "400": {
            "description": "Portefeuille en double (adresse, blockchain et mémo) pour cette application, mémo ou X-address non pris en charge par la blockchain, `address` manquante, `travel_address` invalide, `self_declared: true` alors que `allow_self_declaration` est désactivé, ou `self_declared: true` alors que `ownership_validation_mode` est `FULL`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "examples": {
                  "Duplicate entry": {
                    "value": {
                      "address": [
                        "A wallet address entry with this address and chain already exists."
                      ]
                    }
                  },
                  "Invalid travel address": {
                    "value": {
                      "travel_address": [
                        "Invalid travel address."
                      ]
                    }
                  },
                  "Self-declaration disabled": {
                    "value": {
                      "self_declared": [
                        "Self-declared ownership is disabled for this application."
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/wallet-addresses/{entry_uuid}/": {
      "patch": {
        "summary": "Mettre à jour les métadonnées du titulaire de l'adresse de portefeuille",
        "description": "Mise à jour partielle de holder_name, holder_vendor_data, entity_type et travel_address. Définir travel_address associe une adresse de routage TRP à l'entrée ; les valeurs non valides sont rejetées avec une erreur 400. La réponse ne renvoie que ces quatre champs.",
        "operationId": "updateTravelRuleWalletAddress",
        "x-didit-sdk": {
          "resource": "travel_rule.wallet_addresses",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "entry_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WalletAddressEntryUpdate"
              },
              "example": {
                "holder_name": "Ana Updated",
                "travel_address": "ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH https://verification.didit.me/v3/travel-rule/wallet-addresses/{entry_uuid}/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"holder_name\": \"Ana Updated\", \"travel_address\": \"ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.wallet_addresses.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    holder_name=\"Ana Updated\",\n    travel_address=\"ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.walletAddresses.update(\"11111111-2222-3333-4444-555555555555\", {\n  holder_name: \"Ana Updated\",\n  travel_address: \"ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.WalletAddresses.Update(ctx, \"11111111-2222-3333-4444-555555555555\", didit.WalletAddressEntryUpdateParam{\n\tHolderName:    didit.String(\"Ana Updated\"),\n\tTravelAddress: didit.String(\"ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.WalletAddressEntryUpdate;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().walletAddresses().update(\"11111111-2222-3333-4444-555555555555\", WalletAddressEntryUpdate.builder()\n        .holderName(\"Ana Updated\")\n        .travelAddress(\"ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->walletAddresses->update('11111111-2222-3333-4444-555555555555', [\n    'holder_name' => 'Ana Updated',\n    'travel_address' => 'ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.wallet_addresses.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  holder_name: \"Ana Updated\",\n  travel_address: \"ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.WalletAddresses.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", new WalletAddressEntryUpdate\n{\n    HolderName = \"Ana Updated\",\n    TravelAddress = \"ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Les champs mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletAddressEntryUpdate"
                }
              }
            }
          },
          "400": {
            "description": "`travel_address` n'est pas une Travel Address valide.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid travel address": {
                    "value": {
                      "travel_address": [
                        "Invalid travel address."
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Entrée inconnue ou supprimée."
          }
        }
      },
      "delete": {
        "summary": "Supprimer une adresse de portefeuille",
        "description": "Supprime l'entrée ainsi que ses justificatifs de propriété et les captures d'écran qu'ils avaient stockées. Elle cesse immédiatement de correspondre aux nouveaux transferts et l'adresse est libérée pour un nouvel enregistrement. Les transferts ayant déjà utilisé le portefeuille en conservent leur propre enregistrement et restent lisibles à l'identique. La suppression est irréversible.",
        "operationId": "deleteTravelRuleWalletAddress",
        "x-didit-sdk": {
          "resource": "travel_rule.wallet_addresses",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "entry_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE https://verification.didit.me/v3/travel-rule/wallet-addresses/{entry_uuid}/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.travel_rule.wallet_addresses.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.travelRule.walletAddresses.delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.TravelRule.WalletAddresses.Delete(ctx, \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.travelRule().walletAddresses().delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->travelRule->walletAddresses->delete('11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.travel_rule.wallet_addresses.delete(\"11111111-2222-3333-4444-555555555555\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.TravelRule.WalletAddresses.DeleteAsync(\"11111111-2222-3333-4444-555555555555\");"
          }
        ],
        "responses": {
          "204": {
            "description": "Supprimé."
          },
          "404": {
            "description": "Entrée inconnue ou déjà supprimée."
          },
          "503": {
            "description": "`wallet_address_deletion_incomplete` : un fichier stocké n'a pas pu être supprimé, la suppression s'est donc arrêtée avant de se terminer. L'entrée du carnet d'adresses est toujours présente ; réessayez la même requête pour la finaliser.",
            "content": {
              "application/json": {
                "example": {
                  "detail": "A stored file could not be deleted, so the deletion stopped before it finished. Try again.",
                  "code": "wallet_address_deletion_incomplete"
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/vasps/": {
      "get": {
        "summary": "Rechercher dans l'annuaire VASP",
        "description": "Recherche paginée et triée par nom dans l'annuaire des VASP : les entrées du répertoire partagé, que Didit établit à partir du registre intermédiaire MiCA de l'ESMA, du répertoire public TRISA, du registre mondial LEI et de sa propre sélection, ainsi que les membres du réseau Didit. Chaque ligne indique les routes dont dispose votre application vers ce VASP à ce jour. Le profil de votre propre application n'est jamais répertorié. Les lignes comportent également l'évaluation partagée de diligence raisonnable ainsi que la propre décision de votre application, le filtrage de l'entité et les questionnaires.",
        "operationId": "listTravelRuleVasps",
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 255
            },
            "description": "Un fragment de nom ou d'alias (insensible à la casse), un LEI exact ou un domaine (example.com ou une URL sur celui-ci). Les membres du réseau Didit correspondent selon leur dénomination sociale, leur LEI ou le domaine de leur e-mail de conformité."
          },
          {
            "name": "network",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "GTR",
                "TRUST",
                "VERIFYVASP",
                "SYGNA",
                "TRISA"
              ]
            },
            "description": "Uniquement les entrées de l'annuaire actuellement répertoriées dans l'annuaire des membres d'un réseau."
          },
          {
            "name": "jurisdiction",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Code pays ISO 3166 alpha-2 ou alpha-3. 400 pour toute autre valeur."
          },
          {
            "name": "reachable",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "true : uniquement les VASP vers lesquels votre application dispose d'un itinéraire disponible (membres du réseau Didit inclus). false : uniquement les entrées de l'annuaire qu'elle ne peut pas joindre aujourd'hui."
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "directory",
                "didit"
              ]
            },
            "description": "Uniquement les entrées de l'annuaire, ou uniquement les membres du réseau Didit."
          },
          {
            "name": "risk",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "LOW",
                "MEDIUM",
                "HIGH"
              ]
            },
            "description": "Uniquement les entrées de l'annuaire dont le risk_level correspond à cette tranche. Les membres du réseau Didit, qui ne font pas l'objet d'une notation, ne correspondent jamais."
          },
          {
            "name": "responsiveness",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "RESPONSIVE",
                "UNRESPONSIVE",
                "UNKNOWN"
              ]
            },
            "description": "Uniquement les entrées de l'annuaire dont responsiveness.status a cette valeur. Les membres du réseau Didit ne correspondent jamais."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/travel-rule/vasps/?search=counterparty&reachable=true' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.travel_rule.list_vasps():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.travelRule.listVasps()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.TravelRule.ListVASPsAutoPaging(ctx, didit.TravelRuleListVASPsParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.travelRule().listVasps()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->travelRule->listVasps() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.travel_rule.list_vasps.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.TravelRule.ListVaspsAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Résultats paginés de l'annuaire des VASP, triés par nom.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/VaspDirectoryEntry"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Un filtre n'est pas valide : le corps indique chaque champ, par exemple un réseau, un code pays, une tranche de risque ou un statut de réactivité inconnu.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "jurisdiction": [
                    "Use an ISO 3166 alpha-2 or alpha-3 country code."
                  ],
                  "network": [
                    "\"SWIFT\" is not a valid choice."
                  ]
                }
              }
            }
          }
        },
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "list_vasps",
          "auth": "api_key",
          "server": true
        }
      }
    },
    "/v3/travel-rule/vasps/{vasp_id}/": {
      "get": {
        "summary": "Obtenir une entrée de l'annuaire VASP",
        "description": "Une entrée d'annuaire ou un membre du réseau Didit selon l'identifiant renvoyé par la recherche, avec les mêmes champs et les routes dont dispose votre application vers celui-ci.",
        "operationId": "getTravelRuleVasp",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "retrieve_vasp",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "vasp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'identifiant d'une ligne de GET /v3/travel-rule/vasps/."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/vasps/{vasp_id}/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.retrieve_vasp(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.retrieveVasp(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.RetrieveVASP(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().retrieveVasp(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->retrieveVasp('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.retrieve_vasp(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.RetrieveVaspAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'entrée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaspDirectoryEntry"
                }
              }
            }
          },
          "404": {
            "description": "Aucune entrée ou aucun membre répertorié du réseau Didit ne possède cet identifiant.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No directory entry has this id."
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/vasps/{vasp_id}/decision/": {
      "get": {
        "summary": "Obtenir votre décision sur un VASP",
        "description": "La décision de votre application sur une contrepartie (une entrée de l'annuaire ou un membre du réseau Didit) : approuvé, restreint ou bloqué. Une entité d'une marque sans décision propre suit la décision de la marque, désignée dans inherited_from. Privée pour votre application.",
        "operationId": "getTravelRuleVaspDecision",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "retrieve_vasp_decision",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "vasp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'identifiant d'une ligne de GET /v3/travel-rule/vasps/ : une entrée de l'annuaire ou un membre du réseau Didit."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/vasps/{vasp_id}/decision/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.retrieve_vasp_decision(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.retrieveVaspDecision(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.RetrieveVASPDecision(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().retrieveVaspDecision(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->retrieveVaspDecision('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.retrieve_vasp_decision(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.RetrieveVaspDecisionAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La décision qui s'applique, ou null.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyDecisionResponse"
                },
                "examples": {
                  "Own decision": {
                    "value": {
                      "decision": {
                        "decision": "APPROVED",
                        "reason": "Licensed in DE, questionnaire reviewed",
                        "decided_by": "",
                        "updated_at": "2026-10-14T10:05:00Z",
                        "inherited_from": null
                      }
                    }
                  },
                  "Inherited from the brand": {
                    "value": {
                      "decision": {
                        "decision": "BLOCKED",
                        "reason": "Group refused after review",
                        "decided_by": "",
                        "updated_at": "2026-10-14T10:05:00Z",
                        "inherited_from": {
                          "id": "5e4d3c2b-1a0f-4e9d-8c7b-6a5f4e3d2c1b",
                          "name": "Example Group"
                        }
                      }
                    }
                  },
                  "No decision": {
                    "value": {
                      "decision": null
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune entrée d'annuaire ou aucun membre répertorié du réseau Didit ne possède cet identifiant. Votre propre profil VASP n'est jamais une contrepartie pour vous.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No directory entry or Didit network member has this id."
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Définir votre décision concernant un VASP",
        "description": "Prendre ou modifier la décision de votre application concernant une contrepartie : APPROVED, RESTRICTED ou BLOCKED, avec un motif facultatif. Cela ne modifie jamais l'entrée de l'annuaire partagé et agit uniquement via vos règles de transaction (counterparty_dd_status). Une décision sur une marque couvre également chacune de ses entités qui ne dispose pas de sa propre décision.",
        "operationId": "updateTravelRuleVaspDecision",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "update_vasp_decision",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "vasp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'identifiant d'une ligne de GET /v3/travel-rule/vasps/ : une entrée de l'annuaire ou un membre du réseau Didit."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleCounterpartyDecisionRequest"
              },
              "example": {
                "decision": "BLOCKED",
                "reason": "Unlicensed in its home jurisdiction"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PUT https://verification.didit.me/v3/travel-rule/vasps/{vasp_id}/decision/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"decision\": \"BLOCKED\", \"reason\": \"Unlicensed in its home jurisdiction\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.update_vasp_decision(\n    \"11111111-2222-3333-4444-555555555555\",\n    decision=\"BLOCKED\",\n    reason=\"Unlicensed in its home jurisdiction\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.updateVaspDecision(\"11111111-2222-3333-4444-555555555555\", {\n  decision: \"BLOCKED\",\n  reason: \"Unlicensed in its home jurisdiction\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.UpdateVASPDecision(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleCounterpartyDecisionRequest{\n\tDecision: \"BLOCKED\",\n\tReason:   didit.String(\"Unlicensed in its home jurisdiction\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleCounterpartyDecisionRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().updateVaspDecision(\"11111111-2222-3333-4444-555555555555\", TravelRuleCounterpartyDecisionRequest.builder()\n        .decision(TravelRuleCounterpartyDecisionRequest.Decision.of(\"BLOCKED\"))\n        .reason(\"Unlicensed in its home jurisdiction\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->updateVaspDecision('11111111-2222-3333-4444-555555555555', [\n    'decision' => 'BLOCKED',\n    'reason' => 'Unlicensed in its home jurisdiction',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.update_vasp_decision(\n  \"11111111-2222-3333-4444-555555555555\",\n  decision: \"BLOCKED\",\n  reason: \"Unlicensed in its home jurisdiction\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.UpdateVaspDecisionAsync(\"11111111-2222-3333-4444-555555555555\", new TravelRuleCounterpartyDecisionRequest\n{\n    Decision = \"BLOCKED\",\n    Reason = \"Unlicensed in its home jurisdiction\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La décision telle qu'elle s'applique désormais.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyDecisionResponse"
                },
                "example": {
                  "decision": {
                    "decision": "BLOCKED",
                    "reason": "Unlicensed in its home jurisdiction",
                    "decided_by": "",
                    "updated_at": "2026-10-14T10:05:00Z",
                    "inherited_from": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "La décision est manquante ou n'est pas l'une des valeurs APPROVED, RESTRICTED ou BLOCKED, ou la raison dépasse 255 caractères.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "decision": [
                    "\"MAYBE\" is not a valid choice."
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Aucune entrée d'annuaire ou aucun membre répertorié du réseau Didit ne possède cet identifiant. Votre propre profil VASP n'est jamais une contrepartie pour vous.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No directory entry or Didit network member has this id."
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Effacer votre décision sur un VASP",
        "description": "Effacer la décision propre de votre application sur une contrepartie. La réponse affiche la décision qui s'applique ensuite : null, ou pour une entité d'une marque la décision de la marque, que l'entité suit à nouveau.",
        "operationId": "clearTravelRuleVaspDecision",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "clear_vasp_decision",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "vasp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'identifiant d'une ligne de GET /v3/travel-rule/vasps/ : une entrée de l'annuaire ou un membre du réseau Didit."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE https://verification.didit.me/v3/travel-rule/vasps/{vasp_id}/decision/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.clear_vasp_decision(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.clearVaspDecision(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.ClearVASPDecision(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().clearVaspDecision(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->clearVaspDecision('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.clear_vasp_decision(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.ClearVaspDecisionAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La décision effacée ; le corps indique la décision qui s'applique désormais.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyDecisionResponse"
                },
                "example": {
                  "decision": null
                }
              }
            }
          },
          "404": {
            "description": "Aucune contrepartie ne possède cet identifiant, ou votre application n'a aucune décision propre à son sujet (une décision dont elle hérite uniquement de sa marque ne peut pas être effacée ici : effacez celle de la marque).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Unknown id": {
                    "value": {
                      "detail": "No directory entry or Didit network member has this id."
                    }
                  },
                  "No decision of its own": {
                    "value": {
                      "detail": "This application has no decision of its own on this counterparty."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/vasps/{vasp_id}/screening/": {
      "get": {
        "summary": "Obtenir le filtrage d'entité d'un VASP",
        "description": "Indique si le filtrage de contrepartie est activé pour votre application, ce qu'un filtrage coûte à votre organisation, la durée de validité d'un résultat, ainsi que votre dernier filtrage de sanctions et de presse négative de la contrepartie. La lecture est gratuite.",
        "operationId": "getTravelRuleVaspScreening",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "retrieve_vasp_screening",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "vasp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'identifiant d'une ligne de GET /v3/travel-rule/vasps/ : une entrée de l'annuaire ou un membre du réseau Didit."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/vasps/{vasp_id}/screening/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.retrieve_vasp_screening(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.retrieveVaspScreening(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.RetrieveVASPScreening(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().retrieveVaspScreening(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->retrieveVaspScreening('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.retrieve_vasp_screening(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.RetrieveVaspScreeningAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Votre paramètre de filtrage, son prix et votre dernier filtrage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyScreeningStatus"
                },
                "example": {
                  "enabled": true,
                  "price": "0.20",
                  "fresh_days": 30,
                  "screening": {
                    "id": "7a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                    "status": "Approved",
                    "total_hits": 0,
                    "score": null,
                    "screened_at": "2026-10-14T09:58:00Z",
                    "fresh": true,
                    "flagged": false
                  }
                }
              }
            }
          },
          "403": {
            "description": "Le contrat de votre organisation ne comporte aucun tarif configuré pour le filtrage des contreparties.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No contract rate is configured for this usage type."
                }
              }
            }
          },
          "404": {
            "description": "Aucune entrée d'annuaire ou aucun membre répertorié du réseau Didit ne possède cet identifiant. Votre propre profil VASP n'est jamais une contrepartie pour vous.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No directory entry or Didit network member has this id."
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Filtrer un VASP",
        "description": "Filtrez l'entité contrepartie par rapport aux sanctions et à la presse négative pour votre application. Activation préalable : counterparty_screening_enabled doit être activé dans vos paramètres Travel Rule. Chaque nouveau filtrage est facturé au tarif de filtrage AML d'entreprise de votre organisation ; un filtrage de moins de 30 jours est renvoyé à la place (200, non facturé), sauf si vous envoyez refresh: true. Un seul filtrage d'une contrepartie s'exécute à la fois par application. Le résultat est privé et accessible uniquement à votre application. Les applications sandbox ne font jamais l'objet d'un filtrage.",
        "operationId": "screenTravelRuleVasp",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "screen_vasp",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "vasp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'identifiant d'une ligne de GET /v3/travel-rule/vasps/ : une entrée de l'annuaire ou un membre du réseau Didit."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleCounterpartyScreeningRequest"
              },
              "example": {
                "refresh": false
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/vasps/{vasp_id}/screening/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"refresh\": false}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.screen_vasp(\n    \"11111111-2222-3333-4444-555555555555\",\n    refresh=False,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.screenVasp(\"11111111-2222-3333-4444-555555555555\", {\n  refresh: false,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.ScreenVASP(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleCounterpartyScreeningRequest{\n\tRefresh: didit.Bool(false),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleCounterpartyScreeningRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().screenVasp(\"11111111-2222-3333-4444-555555555555\", TravelRuleCounterpartyScreeningRequest.builder()\n        .refresh(false)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->screenVasp('11111111-2222-3333-4444-555555555555', [\n    'refresh' => false,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.screen_vasp(\n  \"11111111-2222-3333-4444-555555555555\",\n  refresh: false\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.ScreenVaspAsync(\"11111111-2222-3333-4444-555555555555\", new TravelRuleCounterpartyScreeningRequest\n{\n    Refresh = false,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Un filtrage récent existait déjà et a été renvoyé. Rien n'a été facturé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyScreeningResult"
                },
                "example": {
                  "outcome": "reused",
                  "screening": {
                    "id": "7a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                    "status": "Approved",
                    "total_hits": 0,
                    "score": null,
                    "screened_at": "2026-10-14T09:58:00Z",
                    "fresh": true,
                    "flagged": false
                  }
                }
              }
            }
          },
          "201": {
            "description": "Un nouveau filtrage a été exécuté et facturé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyScreeningResult"
                },
                "example": {
                  "outcome": "screened",
                  "screening": {
                    "id": "7a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                    "status": "In Review",
                    "total_hits": 2,
                    "score": 85.0,
                    "screened_at": "2026-10-14T09:58:00Z",
                    "fresh": true,
                    "flagged": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le corps n'est pas valide, ou la contrepartie n'a aucun nom à filtrer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": [
                    "This counterparty has no name to screen."
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Le solde de votre organisation ne peut pas couvrir le filtrage (code insufficient_credits ; rien n'a été exécuté ni facturé), ou votre contrat ne comporte aucun tarif configuré pour celui-ci.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "You don't have enough credits to perform this request. Please top up at https://business.didit.me",
                  "code": "insufficient_credits"
                }
              }
            }
          },
          "404": {
            "description": "Aucune entrée d'annuaire ou aucun membre répertorié du réseau Didit ne possède cet identifiant. Votre propre profil VASP n'est jamais une contrepartie pour vous.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No directory entry or Didit network member has this id."
                }
              }
            }
          },
          "409": {
            "description": "Rien n'a été exécuté et rien n'a été facturé : le filtrage des contreparties est désactivé pour votre application, l'application est en sandbox, ou un filtrage de cette contrepartie est déjà en cours d'exécution.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Screening off": {
                    "value": {
                      "detail": "Counterparty screening is turned off. Enable it in the Travel Rule settings first."
                    }
                  },
                  "Sandbox application": {
                    "value": {
                      "detail": "Counterparty screening does not run for sandbox applications."
                    }
                  },
                  "Already running": {
                    "value": {
                      "detail": "A screening of this counterparty is already running. Try again in a moment."
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Le filtrage n'a pas pu être effectué. Rien n'a été facturé ; réessayez dans un instant.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "The screening provider did not answer. Try again in a moment."
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/vasps/{vasp_id}/questionnaires/": {
      "get": {
        "summary": "Lister les questionnaires de diligence raisonnable avec un VASP",
        "description": "Chaque questionnaire de diligence raisonnable que votre application a envoyé à la contrepartie, du plus récent au plus ancien, avec son statut et, une fois rempli, les réponses. Accessible uniquement à votre application.",
        "operationId": "listTravelRuleVaspQuestionnaires",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "list_vasp_questionnaires",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "vasp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'identifiant d'une ligne de GET /v3/travel-rule/vasps/ : une entrée de l'annuaire ou un membre du réseau Didit."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/vasps/{vasp_id}/questionnaires/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.list_vasp_questionnaires(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.listVaspQuestionnaires(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.ListVASPQuestionnaires(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().listVaspQuestionnaires(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->listVaspQuestionnaires('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.list_vasp_questionnaires(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.ListVaspQuestionnairesAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Vos questionnaires associés à cette contrepartie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyQuestionnaireList"
                },
                "example": {
                  "questionnaires": [
                    {
                      "id": "3f9e8d7c-6b5a-4c3d-9e2f-1a0b9c8d7e6f",
                      "status": "SENT",
                      "form_version": "1",
                      "sent_to": "travelrule@counterparty.example",
                      "sent_at": "2026-10-14T10:00:00Z",
                      "expires_at": "2026-11-13T10:00:00Z",
                      "answered_at": null,
                      "valid_until": null,
                      "current": false,
                      "answers": {}
                    },
                    {
                      "id": "8b7a6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
                      "status": "ANSWERED",
                      "form_version": "1",
                      "sent_to": "travelrule@counterparty.example",
                      "sent_at": "2026-09-02T08:00:00Z",
                      "expires_at": "2026-10-02T08:00:00Z",
                      "answered_at": "2026-09-04T15:20:00Z",
                      "valid_until": "2027-09-04T15:20:00Z",
                      "current": true,
                      "answers": {
                        "legal_name": "Example Counterparty VASP, incorporated in the example jurisdiction.",
                        "licensing": "Crypto-asset service provider authorised under MiCA by its national regulator, licence active.",
                        "jurisdictions": "EU and EEA. We do not serve the United States.",
                        "aml_program": "Written AML/CFT policy, annual independent review, last completed in March 2026.",
                        "compliance_officer": "Head of Compliance, reachable at compliance@counterparty.example.",
                        "sanctions_screening": "Customers at onboarding and daily; counterparties on every transfer.",
                        "transaction_monitoring": "Rule-based monitoring with analyst review; suspicious activity reports filed with the FIU.",
                        "travel_rule": "TRP and email; we answer requests within one business day.",
                        "custody": "Segregated customer wallets held with a qualified custodian, insured.",
                        "ownership": "No shareholder holds 25 percent or more; parent company Example Holding Group.",
                        "record_keeping": "Five-year record-keeping for Travel Rule and transaction data, as our regulator requires.",
                        "data_protection": "Encrypted at rest and in transit, stored in the EU."
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Aucune entrée d'annuaire ou aucun membre répertorié du réseau Didit ne possède cet identifiant. Votre propre profil VASP n'est jamais une contrepartie pour vous.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No directory entry or Didit network member has this id."
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Envoyer un questionnaire de diligence raisonnable à un VASP",
        "description": "Envoyer par e-mail le questionnaire de diligence raisonnable standard de Didit à une adresse de conformité enregistrée pour la contrepartie, avec un lien de réponse à usage unique. La contrepartie dispose de 30 jours pour répondre à chaque question ; les réponses restent valables 365 jours. Un nouvel envoi remplace votre précédent questionnaire resté sans réponse pour la même contrepartie, dont le lien cesse de fonctionner. Un e-mail par minute et par adresse.",
        "operationId": "sendTravelRuleVaspQuestionnaire",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "send_vasp_questionnaire",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "vasp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'identifiant d'une ligne de GET /v3/travel-rule/vasps/ : une entrée de l'annuaire ou un membre du réseau Didit."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleCounterpartyQuestionnaireRequest"
              },
              "example": {
                "sent_to": "travelrule@counterparty.example"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/vasps/{vasp_id}/questionnaires/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"sent_to\": \"travelrule@counterparty.example\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.send_vasp_questionnaire(\n    \"11111111-2222-3333-4444-555555555555\",\n    sent_to=\"travelrule@counterparty.example\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.sendVaspQuestionnaire(\"11111111-2222-3333-4444-555555555555\", {\n  sent_to: \"travelrule@counterparty.example\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.SendVASPQuestionnaire(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleCounterpartyQuestionnaireRequest{\n\tSentTo: didit.String(\"travelrule@counterparty.example\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleCounterpartyQuestionnaireRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().sendVaspQuestionnaire(\"11111111-2222-3333-4444-555555555555\", TravelRuleCounterpartyQuestionnaireRequest.builder()\n        .sentTo(\"travelrule@counterparty.example\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->sendVaspQuestionnaire('11111111-2222-3333-4444-555555555555', [\n    'sent_to' => 'travelrule@counterparty.example',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.send_vasp_questionnaire(\n  \"11111111-2222-3333-4444-555555555555\",\n  sent_to: \"travelrule@counterparty.example\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.SendVaspQuestionnaireAsync(\"11111111-2222-3333-4444-555555555555\", new TravelRuleCounterpartyQuestionnaireRequest\n{\n    SentTo = \"travelrule@counterparty.example\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "202": {
            "description": "Le questionnaire a été envoyé par e-mail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyQuestionnaire"
                },
                "example": {
                  "id": "3f9e8d7c-6b5a-4c3d-9e2f-1a0b9c8d7e6f",
                  "status": "SENT",
                  "form_version": "1",
                  "sent_to": "travelrule@counterparty.example",
                  "sent_at": "2026-10-14T10:00:00Z",
                  "expires_at": "2026-11-13T10:00:00Z",
                  "answered_at": null,
                  "valid_until": null,
                  "current": false,
                  "answers": {}
                }
              }
            }
          },
          "400": {
            "description": "sent_to n'est pas une adresse e-mail valide ou n'est pas une adresse de conformité enregistrée pour la contrepartie, ou la contrepartie n'a aucune adresse de conformité enregistrée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not on record": {
                    "value": {
                      "sent_to": [
                        "Send the questionnaire to a compliance address on record for this counterparty."
                      ]
                    }
                  },
                  "No address": {
                    "value": {
                      "sent_to": [
                        "No compliance address is on record for this counterparty. Add a contact for it first."
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune entrée d'annuaire ou aucun membre répertorié du réseau Didit ne possède cet identifiant. Votre propre profil VASP n'est jamais une contrepartie pour vous.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No directory entry or Didit network member has this id."
                }
              }
            }
          },
          "429": {
            "description": "Un questionnaire a été envoyé à cette adresse il y a moins d'une minute."
          },
          "503": {
            "description": "L'e-mail n'a pas pu être envoyé et aucun questionnaire n'a été créé. Réessayez dans un instant."
          }
        }
      }
    },
    "/v3/transactions/{transaction_id}/travel-rule/": {
      "patch": {
        "summary": "Terminer, annuler, renvoyer ou mettre à jour le portefeuille du donneur d'ordre d'un transfert Travel Rule",
        "description": "Fournissez `payment_txn_id` pour signaler le hash on-chain et passer un transfert sortant COMPLETED à FINISHED (son homologue sur le rail INTERNAL passe également à FINISHED), `{\"action\": \"cancel\"}` pour annuler un transfert non terminal, ou `{\"action\": \"resend\"}` pour router à nouveau un transfert sortant bloqué dans COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA (améliorez d'abord les données de la contrepartie, par ex. en ajoutant une travel_address à l'entrée du portefeuille de destination). resend s'applique uniquement aux transferts sortants. `{\"action\": \"update_compliance_email\", \"compliance_email\": \"desk@example.com\"}` remplace l'e-mail de conformité d'un transfert sortant se trouvant dans l'un de ces trois statuts, la solution pour `reason: email_undeliverable` : le statut ne change pas, et le prochain `resend` envoie la requête à cette adresse. Un renvoi est mis en file d'attente et ne s'exécute pas au sein de la requête : la réponse montre le transfert de retour dans AWAITING_COUNTERPARTY avec une entrée d'historique `resend queued` et une `delivery` en file d'attente, et sa destination arrive via un webhook `travel_rule.status.updated`. Lorsque le transfert est passé par GTR, VerifyVASP ou Sygna Bridge, le réseau est informé du hash on-chain ou de l'annulation après la réponse, avec des réessais ; `delivery` indique où en est ce message. `{\"action\": \"update_originator_wallet\", \"wallet_address\": \"...\"}` enregistre le portefeuille depuis lequel les fonds sont réellement partis sur un transfert sortant, par exemple l'adresse depuis laquelle un retrait UTXO a été diffusé plutôt que le portefeuille principal que vous aviez déclaré. Cela modifie uniquement l'enregistrement : rien n'est renvoyé à la contrepartie et le statut reste le même. Le donneur d'ordre devient `chain_details.originator` avec `source: updated`, la modification est ajoutée à la `timeline` avec l'ancien et le nouveau portefeuille, et l'homologue sur le rail INTERNAL du transfert est mis à jour de la même manière. `{\"action\": \"beneficiary_vasp\", \"beneficiary_vasp\": \"<directory VASP id>\"}` désigne vous-même la contrepartie lorsque la découverte a échoué, sur un transfert sortant dans COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA : le transfert est routé vers ce VASP et envoyé à nouveau.",
        "operationId": "patchTravelRuleTransfer",
        "x-didit-sdk": {
          "resource": "transactions.travel_rule",
          "method": "update_transfer",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID de transaction stable attribué par Didit propriétaire du transfert.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleTransferPatchRequest"
              },
              "examples": {
                "Finish": {
                  "value": {
                    "payment_txn_id": "0xchainhash"
                  }
                },
                "Cancel": {
                  "value": {
                    "action": "cancel"
                  }
                },
                "Resend": {
                  "value": {
                    "action": "resend"
                  }
                },
                "Update compliance email": {
                  "value": {
                    "action": "update_compliance_email",
                    "compliance_email": "desk@example.com"
                  }
                },
                "Update originator wallet": {
                  "value": {
                    "action": "update_originator_wallet",
                    "wallet_address": "bc1qOriginatorInputAddress01"
                  }
                },
                "Name the counterparty": {
                  "value": {
                    "action": "beneficiary_vasp",
                    "beneficiary_vasp": "9f1c2b34-5d6e-4f70-8a91-b2c3d4e5f607"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"payment_txn_id\": \"0xchainhash\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.travel_rule.update_transfer(\n    \"11111111-2222-3333-4444-555555555555\",\n    payment_txn_id=\"0xchainhash\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.travelRule.updateTransfer(\"11111111-2222-3333-4444-555555555555\", {\n  payment_txn_id: \"0xchainhash\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.TravelRule.UpdateTransfer(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleTransferPatchRequest{\n\tPaymentTxnID: didit.String(\"0xchainhash\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleTransferPatchRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().travelRule().updateTransfer(\"11111111-2222-3333-4444-555555555555\", TravelRuleTransferPatchRequest.builder()\n        .paymentTxnId(\"0xchainhash\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->travelRule->updateTransfer('11111111-2222-3333-4444-555555555555', [\n    'payment_txn_id' => '0xchainhash',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.travel_rule.update_transfer(\n  \"11111111-2222-3333-4444-555555555555\",\n  payment_txn_id: \"0xchainhash\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.TravelRule.UpdateTransferAsync(\"11111111-2222-3333-4444-555555555555\", new TravelRuleTransferPatchRequest\n{\n    PaymentTxnId = \"0xchainhash\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le transfert mis à jour. Après `update_compliance_email`, son statut reste inchangé et conserve `reason: email_undeliverable` jusqu'au prochain `resend`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleTransferDetail"
                }
              }
            }
          },
          "400": {
            "description": "Ni payment_txn_id ni une action prise en charge n'ont été fournis, `compliance_email` est manquant ou n'est pas une adresse e-mail lors de `update_compliance_email`, ou, pour `update_originator_wallet`, aucun wallet_address, un portefeuille ou memo que la blockchain du transfert ne peut pas acheminer, ou un portefeuille qui ne fait pas partie des entrées UTXO du transfert, ou `beneficiary_vasp` est manquant ou n'est pas un identifiant de VASP valide dans l'annuaire.",
            "content": {
              "application/json": {
                "examples": {
                  "No action": {
                    "value": {
                      "detail": [
                        "Provide payment_txn_id, action=cancel, action=resend, action=beneficiary_vasp, action=update_originator_wallet or action=update_compliance_email."
                      ]
                    }
                  },
                  "Invalid compliance email": {
                    "value": {
                      "compliance_email": [
                        "Enter a valid email address."
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Transaction inconnue, la transaction n'a aucun transfert Travel Rule, ou (action `beneficiary_vasp`) aucune entrée de l'annuaire ne possède cet identifiant."
          },
          "409": {
            "description": "Le transfert n'est pas dans un état permettant cette opération (par exemple, pas COMPLETED/sortant pour finish, déjà terminal pour cancel, ou pas un transfert sortant dans un statut réexpédiable pour resend). `update_compliance_email` renvoie `409` pour un transfert entrant, ainsi que pour un transfert sortant en dehors de COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE et NOT_ENOUGH_COUNTERPARTY_DATA. `update_originator_wallet` renvoie `409` pour un transfert entrant, annulé ou expiré. `beneficiary_vasp` renvoie `409` sauf si le transfert est sortant et dans l'état COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA.",
            "content": {
              "application/json": {
                "examples": {
                  "Cancel from a terminal status": {
                    "value": {
                      "detail": "Transfer is already in a terminal state."
                    }
                  },
                  "Resend not allowed": {
                    "value": {
                      "detail": "Transfer cannot be resent from its current state."
                    }
                  },
                  "Finish not allowed": {
                    "value": {
                      "detail": "Transfer must be an outbound transfer in COMPLETED status to finish."
                    }
                  },
                  "Compliance email cannot change": {
                    "value": {
                      "detail": "The compliance email of this transfer cannot change from its current state."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/transactions/{transaction_id}/travel-rule/ownership/": {
      "post": {
        "summary": "Confirmer ou refuser la propriété du portefeuille",
        "description": "Résolvez un transfert en attente de propriété du portefeuille : appelez-le de votre côté du transfert lorsqu'il est à l'état UNCONFIRMED_OWNERSHIP, ou lorsqu'il s'agit d'un transfert entrant à l'état ON_HOLD. La confirmation marque l'entrée correspondante du carnet d'adresses de portefeuilles comme vérifiée quant à sa propriété (pour un transfert entrant ON_HOLD sans entrée, Didit en crée une à partir de beneficiary_data.wallet_address) et exécute la correspondance du nom du bénéficiaire des deux côtés du transfert ; le refus rejette les deux côtés. Un transfert entrant dont le dépôt est déjà réglé passe à FINISHED lorsque la correspondance réussit. Lorsque le portefeuille de la contrepartie a été déclaré auto-hébergé (counterparty.payment_method.method_type: unhosted_wallet), la confirmation enregistre que le client a vérifié qui contrôle ce portefeuille et finalise le transfert (COMPLETED) dans les deux sens, ou FINISHED pour un dépôt entrant dont le hash on-chain est déjà connu. Le portefeuille vérifié est celui de la contrepartie : la destination d'un retrait sortant, ou la source (le portefeuille du donneur d'ordre) d'un dépôt entrant. S'il ne figure pas encore dans votre carnet d'adresses de portefeuilles, Didit l'ajoute comme vérifié quant à sa propriété sous le nom de la contrepartie ; si le carnet le contient déjà sous un nom de titulaire différent, le transfert passe à COUNTERPARTY_MISMATCHED_DATA. Pour un transfert TRP entrant à l'état UNCONFIRMED_OWNERSHIP, ON_HOLD ou COUNTERPARTY_MISMATCHED_DATA, Didit transmet plutôt votre décision au VASP d'origine : l'approbation renvoie l'adresse de paiement (wallet_address ou l'adresse de l'entrée correspondante) et fait passer le transfert à COMPLETED, tandis que le refus le rejette. Le même appel tranche également un transfert entrant envoyé par une contrepartie GTR ou Sygna Bridge et qui attend votre examen (`UNCONFIRMED_OWNERSHIP`, `ON_HOLD` ou `COUNTERPARTY_MISMATCHED_DATA`) : `confirmed: true` l'approuve (transmettez `wallet_address` lorsque le transfert n'en indique aucune) et `confirmed: false` le refuse, et le réseau reçoit la réponse après celle-ci, avec des réessais. VerifyVASP reçoit sa réponse au moment où il formule la demande ; ainsi, un transfert VerifyVASP qui nécessiterait votre examen est refusé immédiatement et ne peut pas être tranché ultérieurement.",
        "operationId": "confirmTravelRuleOwnership",
        "x-didit-sdk": {
          "resource": "transactions.travel_rule",
          "method": "confirm_ownership",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID stable attribué par Didit à la transaction que votre application détient pour ce transfert : la transaction côté bénéficiaire sur un transfert via le réseau INTERNAL, ou la transaction que vous avez créée (entrante ou sortante) lorsque le portefeuille de la contrepartie a été déclaré auto-hébergé.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleOwnershipConfirmRequest"
              },
              "example": {
                "confirmed": true
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/ownership/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"confirmed\": true}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.travel_rule.confirm_ownership(\n    \"11111111-2222-3333-4444-555555555555\",\n    confirmed=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.travelRule.confirmOwnership(\"11111111-2222-3333-4444-555555555555\", {\n  confirmed: true,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.TravelRule.ConfirmOwnership(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleOwnershipConfirmRequest{\n\tConfirmed: true,\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleOwnershipConfirmRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().travelRule().confirmOwnership(\"11111111-2222-3333-4444-555555555555\", TravelRuleOwnershipConfirmRequest.builder()\n        .confirmed(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->travelRule->confirmOwnership('11111111-2222-3333-4444-555555555555', [\n    'confirmed' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.travel_rule.confirm_ownership(\n  \"11111111-2222-3333-4444-555555555555\",\n  confirmed: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.TravelRule.ConfirmOwnershipAsync(\"11111111-2222-3333-4444-555555555555\", new TravelRuleOwnershipConfirmRequest\n{\n    Confirmed = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le transfert mis à jour. Pour un transfert entrant, les originator_data/beneficiary_data de la contrepartie restent masqués (`data_masked: true`) jusqu'à ce que l'actionnariat soit confirmé, puis `data_unmasked` enregistre quand, pourquoi et par qui.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleTransferDetail"
                }
              }
            }
          },
          "409": {
            "description": "Le transfert n'est pas en attente de confirmation de propriété, aucune entrée du carnet d'adresses de portefeuille ne correspond à son portefeuille de contrepartie, un transfert INTERNAL provenant d'un autre client Didit nécessite une preuve de contrôle (un message signé ou un dépôt test) avant de pouvoir être confirmé, ou une réponse a déjà été apportée au transfert de réseau via son réseau (un transfert VerifyVASP, ou un transfert GTR ou Sygna Bridge pour lequel vous ou Didit avez déjà pris une décision).",
            "content": {
              "application/json": {
                "examples": {
                  "Not awaiting confirmation": {
                    "value": {
                      "detail": "Transfer is not awaiting ownership confirmation."
                    }
                  },
                  "No matching address book entry": {
                    "value": {
                      "detail": "wallet address entry no longer available"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation : confirmed est manquant, une approbation TRP entrante n'a pas de wallet_address ni d'adresse de repli, ou `confirmed: true` sur un transfert déclaré vers un portefeuille auto-hébergé qui ne nomme aucun portefeuille de contrepartie alors qu'aucune `wallet_address` n'a été envoyée.",
            "content": {
              "application/json": {
                "examples": {
                  "No payment address": {
                    "value": {
                      "wallet_address": [
                        "wallet_address is required to approve."
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Transaction inconnue, ou la transaction n'a aucun transfert Travel Rule."
          },
          "502": {
            "description": "Transfert TRP entrant uniquement : Didit n'a pas pu transmettre votre décision au VASP d'origine, le statut du transfert ne change donc pas.",
            "content": {
              "application/json": {
                "examples": {
                  "Callback not delivered": {
                    "value": {
                      "detail": "Counterparty inquiry-resolution callback could not be delivered."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/transactions/{transaction_id}/travel-rule/messages/": {
      "get": {
        "summary": "Lister les messages Travel Rule",
        "description": "Messages et demandes de documents échangés avec le VASP contrepartie concernant ce transfert.",
        "operationId": "listTravelRuleMessages",
        "x-didit-sdk": {
          "resource": "transactions.travel_rule",
          "method": "list_messages",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID de transaction stable attribué par Didit propriétaire du transfert.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/messages/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.travel_rule.list_messages(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.travelRule.listMessages(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.TravelRule.ListMessages(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().travelRule().listMessages(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->travelRule->listMessages('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.transactions.travel_rule.list_messages(\"11111111-2222-3333-4444-555555555555\").each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.TravelRule.ListMessagesAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Les messages, du plus ancien au plus récent.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TravelRuleMessage"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Transaction ou token inconnu, ou aucun transfert Travel Rule sur la transaction."
          }
        }
      },
      "post": {
        "summary": "Envoyer un message Travel Rule ou une demande de document",
        "description": "Envoie un message ou une demande de document au VASP de contrepartie. Fonctionne sur les transferts INTERNAL (l'autre client Didit le voit de son côté de la paire) et les transferts EMAIL (la contrepartie reçoit un e-mail et répond dans le portail de collecte). Un transfert via TRP, GTR, TRUST, VerifyVASP ou Sygna ne transporte aucun message, car ces protocoles n'en disposent pas. Limites : 100 messages par transfert, 5000 caractères par corps, 10 documents demandés, 5 fichiers de 10 MB chacun.",
        "operationId": "createTravelRuleMessage",
        "x-didit-sdk": {
          "resource": "transactions.travel_rule",
          "method": "create_message",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID de transaction stable attribué par Didit propriétaire du transfert.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleMessageCreateRequest"
              },
              "example": {
                "kind": "DOCUMENT_REQUEST",
                "body": "Please confirm the date of birth of the beneficiary.",
                "requested_documents": [
                  "Proof of address"
                ]
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleMessageCreateRequest"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/messages/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"kind\": \"DOCUMENT_REQUEST\", \"body\": \"Please confirm the date of birth of the beneficiary.\", \"requested_documents\": [\"Proof of address\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.travel_rule.create_message(\n    \"11111111-2222-3333-4444-555555555555\",\n    kind=\"DOCUMENT_REQUEST\",\n    body=\"Please confirm the date of birth of the beneficiary.\",\n    requested_documents=[\"Proof of address\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.travelRule.createMessage(\"11111111-2222-3333-4444-555555555555\", {\n  kind: \"DOCUMENT_REQUEST\",\n  body: \"Please confirm the date of birth of the beneficiary.\",\n  requested_documents: [\"Proof of address\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.TravelRule.CreateMessage(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleMessageCreateRequest{\n\tKind:               didit.Some(didit.TravelRuleMessageCreateRequestKind(\"DOCUMENT_REQUEST\")),\n\tBody:               didit.String(\"Please confirm the date of birth of the beneficiary.\"),\n\tRequestedDocuments: didit.Some([]string{\"Proof of address\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.TravelRuleMessageCreateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().travelRule().createMessage(\"11111111-2222-3333-4444-555555555555\", TravelRuleMessageCreateRequest.builder()\n        .kind(TravelRuleMessageCreateRequest.Kind.of(\"DOCUMENT_REQUEST\"))\n        .body(\"Please confirm the date of birth of the beneficiary.\")\n        .requestedDocuments(List.of(\"Proof of address\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->travelRule->createMessage('11111111-2222-3333-4444-555555555555', [\n    'kind' => 'DOCUMENT_REQUEST',\n    'body' => 'Please confirm the date of birth of the beneficiary.',\n    'requested_documents' => ['Proof of address'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.travel_rule.create_message(\n  \"11111111-2222-3333-4444-555555555555\",\n  kind: \"DOCUMENT_REQUEST\",\n  body: \"Please confirm the date of birth of the beneficiary.\",\n  requested_documents: [\"Proof of address\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.TravelRule.CreateMessageAsync(\"11111111-2222-3333-4444-555555555555\", new TravelRuleMessageCreateRequest\n{\n    Kind = new TravelRuleMessageCreateRequestKind(\"DOCUMENT_REQUEST\"),\n    Body = \"Please confirm the date of birth of the beneficiary.\",\n    RequestedDocuments = new string[] { \"Proof of address\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Le message enregistré.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleMessage"
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide, type ou taille de fichier non accepté, plus de 100 messages sur le transfert, ou un `reply_to` qui n'est pas un message de ce transfert.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "requested_documents": [
                    "Name at least one document the counterparty should send."
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Transaction ou token inconnu, ou aucun transfert Travel Rule sur la transaction."
          },
          "409": {
            "description": "Aucun message ne peut parvenir à la contrepartie. `detail` en indique la raison : le transfert s'effectue via un réseau de transfert (TRP, GTR, TRUST, VerifyVASP ou Sygna), il n'a pas encore de contrepartie, les données d'un transfert INTERNAL ne correspondaient pas au titulaire du portefeuille et rien n'a donc atteint le destinataire, ou le lien de récupération d'un transfert EMAIL a expiré ou le transfert est clos.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/pickup/{token}/": {
      "get": {
        "summary": "Obtenir les informations de collecte par e-mail",
        "description": "Public, non authentifié. Permet à un VASP contrepartie n'utilisant pas Didit de prévisualiser l'échange en attente depuis le lien de récupération reçu par e-mail. Le token lui-même sert d'authentification.",
        "operationId": "getTravelRulePickup",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "retrieve_pickup",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "La valeur `?contact=` du lien, à savoir le contact auquel le lien a été envoyé. Renvoyée à l'identique dans `contact` ; elle n'est pas validée."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://verification.didit.me/v3/travel-rule/pickup/{token}/"
          }
        ],
        "responses": {
          "200": {
            "description": "Aperçu du retrait.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRulePickupInfo"
                },
                "example": {
                  "reference": "33333333-4444-5555-6666-777777777777",
                  "requested_at": "2026-07-05T10:00:00Z",
                  "originator_vasp_name": "Origin CASP SL",
                  "originator_vasp_lei": "529900EXAMPLEORIG001",
                  "recipient_vasp_name": "Example Counterparty VASP",
                  "language": "es",
                  "amount": "0.250000000000000000",
                  "currency": "ETH",
                  "fiat_amount": "",
                  "fiat_currency": "",
                  "chain": "ETH",
                  "beneficiary_wallet": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
                  "status": "AWAITING_COUNTERPARTY",
                  "ivms_version": "ivms101.2023",
                  "deadline_at": "2026-07-07T10:00:00Z",
                  "reminders_sent": 0,
                  "contact": "",
                  "decline_reasons": [
                    "data_mismatch",
                    "not_our_customer",
                    "wallet_not_hosted",
                    "sanctions",
                    "risk_appetite",
                    "jurisdiction",
                    "insufficient_data",
                    "other"
                  ],
                  "join_invitation": {
                    "eligible": false,
                    "url": ""
                  },
                  "originator_data": {
                    "name": "Jane Doe",
                    "wallet_address": "0x77ccff0cc624a53cd8b8d8703ced826710211ec7"
                  },
                  "beneficiary_data": {
                    "name": "Ana Diaz",
                    "wallet_address": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb"
                  },
                  "ivms_request": {
                    "originator": {
                      "originatorPersons": [
                        {
                          "naturalPerson": {
                            "name": {
                              "nameIdentifier": [
                                {
                                  "primaryIdentifier": "Doe",
                                  "secondaryIdentifier": "Jane",
                                  "nameIdentifierType": "LEGL"
                                }
                              ]
                            }
                          }
                        }
                      ],
                      "accountNumber": [
                        "0x77ccff0cc624a53cd8b8d8703ced826710211ec7"
                      ]
                    },
                    "beneficiary": {
                      "beneficiaryPersons": [
                        {
                          "naturalPerson": {
                            "name": {
                              "nameIdentifier": [
                                {
                                  "primaryIdentifier": "Diaz",
                                  "secondaryIdentifier": "Ana",
                                  "nameIdentifierType": "LEGL"
                                }
                              ]
                            }
                          }
                        }
                      ],
                      "accountNumber": [
                        "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb"
                      ]
                    }
                  },
                  "data_masked": false
                }
              }
            }
          },
          "404": {
            "description": "Token inconnu."
          },
          "410": {
            "description": "La fenêtre est fermée : la contrepartie a déjà répondu, le transfert a quitté l'état AWAITING_COUNTERPARTY, ou le délai a expiré."
          }
        }
      }
    },
    "/v3/travel-rule/pickup/{token}/respond/": {
      "post": {
        "summary": "Répondre à une récupération sur le canal e-mail",
        "description": "Public, non authentifié. Accepte ou refuse l'échange depuis le lien de retrait envoyé par e-mail. En cas d'acceptation, beneficiary_name est vérifié par rapport à la politique name_matching_strictness du donneur d'ordre.",
        "operationId": "respondTravelRulePickup",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "respond_pickup",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "La valeur `?contact=` du lien. Utilisée lorsque le corps n'envoie aucun `contact`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRulePickupRespondRequest"
              },
              "example": {
                "decision": "accept",
                "beneficiary_name": "Carlos Ruiz"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/pickup/{token}/respond/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"decision\": \"accept\", \"beneficiary_name\": \"Carlos Ruiz\"}'"
          }
        ],
        "responses": {
          "200": {
            "description": "Le statut d'échange résultant : COMPLETED ou COUNTERPARTY_MISMATCHED_DATA après une acceptation, COUNTERPARTY_VASP_GENERAL_DECLINE après un refus, qui renvoie également `decline_reason`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "decline_reason": {
                      "type": "string",
                      "description": "Présent après un refus."
                    }
                  }
                },
                "examples": {
                  "accepted": {
                    "value": {
                      "status": "COMPLETED"
                    }
                  },
                  "declined": {
                    "value": {
                      "status": "COUNTERPARTY_VASP_GENERAL_DECLINE",
                      "decline_reason": "not_our_customer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Un champ n'est pas valide : par exemple `decision` manquant ou différent de `accept` ou `decline`, `decline_detail` manquant lors d'un refus avec `decline_reason: other`, une réponse `ivms_response` qui n'est pas un objet IVMS 101 ou qui dépasse 16384 caractères, ou un `contact` dans le corps qui n'est pas un UUID (`{\"contact\": [\"Must be a valid UUID.\"]}`).",
            "content": {
              "application/json": {
                "example": {
                  "decline_detail": [
                    "Say what the reason is when you choose another reason."
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Token inconnu."
          },
          "410": {
            "description": "La fenêtre est fermée : la contrepartie a déjà répondu, le transfert a quitté l'état AWAITING_COUNTERPARTY, ou le délai a expiré."
          }
        }
      }
    },
    "/v3/travel-rule/pickup/{token}/messages/": {
      "get": {
        "summary": "Lister les messages de récupération",
        "description": "Public, non authentifié. Les messages d'un transfert par canal EMAIL tels que le VASP contrepartie les lit : ce que le client a envoyé est `INBOUND` et est signé avec le nom du VASP du client. Le token sert d'authentification.",
        "operationId": "listTravelRulePickupMessages",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "list_pickup_messages",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://verification.didit.me/v3/travel-rule/pickup/{token}/messages/"
          }
        ],
        "responses": {
          "200": {
            "description": "Les messages, du plus ancien au plus récent, du côté de la contrepartie.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TravelRuleMessage"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Token inconnu."
          },
          "410": {
            "description": "Le lien de récupération a expiré ou le transfert est fermé."
          }
        }
      },
      "post": {
        "summary": "Répondre dans le portail de récupération",
        "description": "Public, non authentifié. Le VASP contrepartie répond sur un transfert par canal EMAIL. Même corps que les messages de la transaction ; les pièces jointes doivent être au format PDF, PNG, JPEG ou WebP. Le token sert d'authentification.",
        "operationId": "createTravelRulePickupMessage",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "create_pickup_message",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleMessageCreateRequest"
              },
              "example": {
                "kind": "MESSAGE",
                "body": "Attached is the proof of address of the wallet holder."
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleMessageCreateRequest"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/pickup/{token}/messages/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"kind\": \"MESSAGE\", \"body\": \"Attached is the proof of address of the wallet holder.\"}'"
          }
        ],
        "responses": {
          "201": {
            "description": "Le message enregistré.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleMessage"
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide, type ou taille de fichier non accepté, plus de 100 messages sur le transfert, ou un `reply_to` qui n'est pas un message de ce transfert.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "requested_documents": [
                    "Name at least one document the counterparty should send."
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Token inconnu."
          },
          "410": {
            "description": "Le lien de récupération a expiré ou le transfert est fermé."
          }
        }
      }
    },
    "/v3/travel-rule/inbound/": {
      "post": {
        "summary": "Enregistrer un transfert entrant après dépôt (sunrise)",
        "description": "Enregistrer les données Travel Rule pour un dépôt crypto déjà réglé on-chain avant tout échange. Crée une transaction travelRule entrante (ou réutilise un dépôt non réclamé) et rapproche le transfert de votre carnet d'adresses de portefeuilles. Pour une transaction nouvellement créée, Didit envoie d'abord transaction.created, suivi des webhooks travel_rule.status.updated.",
        "operationId": "registerTravelRuleInbound",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "register_inbound",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleInboundRequest"
              },
              "example": {
                "chain": "ETH",
                "txid": "0xdeposit-hash",
                "wallet_address": "0xYourDepositWallet",
                "amount": "500.00",
                "currency": "USDC",
                "originator_data": {
                  "name": "Origin CASP SL"
                },
                "beneficiary_data": {
                  "name": "Ana Diaz"
                },
                "originating_vasp": {
                  "name": "Origin CASP SL",
                  "lei": "",
                  "travel_address": "ta9JbXbsBSuS5ozArJRFVgvBHMVnDGUnrPPChSZYQsuZTn3kPrJXUQ7RSLUEJ5KjyPvr8C9sAxmPtZfGsQVKCi4n8ShxP9BkbDdbtjtA9aumNybAZ1BxC"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/inbound/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"chain\":\"ETH\",\"txid\":\"0xdeposit-hash\",\"wallet_address\":\"0xYourDepositWallet\",\"amount\":\"500.00\",\"currency\":\"USDC\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.register_inbound(\n    chain=\"ETH\",\n    txid=\"0xdeposit-hash\",\n    wallet_address=\"0xYourDepositWallet\",\n    amount=\"500.00\",\n    currency=\"USDC\",\n    originator_data={\"name\": \"Origin CASP SL\"},\n    beneficiary_data={\"name\": \"Ana Diaz\"},\n    originating_vasp={\n        \"name\": \"Origin CASP SL\",\n        \"lei\": \"\",\n        \"travel_address\": \"ta9JbXbsBSuS5ozArJRFVgvBHMVnDGUnrPPChSZYQsuZTn3kPrJXUQ7RSLUEJ5KjyPvr8C9sAxmPtZfGsQVKCi4n8ShxP9BkbDdbtjtA9aumNybAZ1BxC\",\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.registerInbound({\n  chain: \"ETH\",\n  txid: \"0xdeposit-hash\",\n  wallet_address: \"0xYourDepositWallet\",\n  amount: \"500.00\",\n  currency: \"USDC\",\n  originator_data: { name: \"Origin CASP SL\" },\n  beneficiary_data: { name: \"Ana Diaz\" },\n  originating_vasp: {\n    name: \"Origin CASP SL\",\n    lei: \"\",\n    travel_address: \"ta9JbXbsBSuS5ozArJRFVgvBHMVnDGUnrPPChSZYQsuZTn3kPrJXUQ7RSLUEJ5KjyPvr8C9sAxmPtZfGsQVKCi4n8ShxP9BkbDdbtjtA9aumNybAZ1BxC\",\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.RegisterInbound(ctx, didit.TravelRuleInboundRequest{\n\tChain:           \"ETH\",\n\tTxid:            \"0xdeposit-hash\",\n\tWalletAddress:   \"0xYourDepositWallet\",\n\tAmount:          \"500.00\",\n\tCurrency:        \"USDC\",\n\tOriginatorData:  didit.Some(map[string]any{\"name\": \"Origin CASP SL\"}),\n\tBeneficiaryData: didit.Some(map[string]any{\"name\": \"Ana Diaz\"}),\n\tOriginatingVASP: didit.Some(didit.TravelRuleInboundRequestOriginatingVASP{\n\t\tName:          didit.String(\"Origin CASP SL\"),\n\t\tLei:           didit.String(\"\"),\n\t\tTravelAddress: didit.String(\"ta9JbXbsBSuS5ozArJRFVgvBHMVnDGUnrPPChSZYQsuZTn3kPrJXUQ7RSLUEJ5KjyPvr8C9sAxmPtZfGsQVKCi4n8ShxP9BkbDdbtjtA9aumNybAZ1BxC\"),\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.TravelRuleInboundRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().registerInbound(TravelRuleInboundRequest.builder()\n        .chain(\"ETH\")\n        .txid(\"0xdeposit-hash\")\n        .walletAddress(\"0xYourDepositWallet\")\n        .amount(\"500.00\")\n        .currency(\"USDC\")\n        .originatorData(Map.of(\"name\", \"Origin CASP SL\"))\n        .beneficiaryData(Map.of(\"name\", \"Ana Diaz\"))\n        .originatingVasp(TravelRuleInboundRequest.OriginatingVasp.builder()\n                .name(\"Origin CASP SL\")\n                .lei(\"\")\n                .travelAddress(\"ta9JbXbsBSuS5ozArJRFVgvBHMVnDGUnrPPChSZYQsuZTn3kPrJXUQ7RSLUEJ5KjyPvr8C9sAxmPtZfGsQVKCi4n8ShxP9BkbDdbtjtA9aumNybAZ1BxC\")\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->registerInbound([\n    'chain' => 'ETH',\n    'txid' => '0xdeposit-hash',\n    'wallet_address' => '0xYourDepositWallet',\n    'amount' => '500.00',\n    'currency' => 'USDC',\n    'originator_data' => ['name' => 'Origin CASP SL'],\n    'beneficiary_data' => ['name' => 'Ana Diaz'],\n    'originating_vasp' => [\n        'name' => 'Origin CASP SL',\n        'lei' => '',\n        'travel_address' => 'ta9JbXbsBSuS5ozArJRFVgvBHMVnDGUnrPPChSZYQsuZTn3kPrJXUQ7RSLUEJ5KjyPvr8C9sAxmPtZfGsQVKCi4n8ShxP9BkbDdbtjtA9aumNybAZ1BxC',\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.register_inbound(\n  chain: \"ETH\",\n  txid: \"0xdeposit-hash\",\n  wallet_address: \"0xYourDepositWallet\",\n  amount: \"500.00\",\n  currency: \"USDC\",\n  originator_data: { name: \"Origin CASP SL\" },\n  beneficiary_data: { name: \"Ana Diaz\" },\n  originating_vasp: {\n    name: \"Origin CASP SL\",\n    lei: \"\",\n    travel_address: \"ta9JbXbsBSuS5ozArJRFVgvBHMVnDGUnrPPChSZYQsuZTn3kPrJXUQ7RSLUEJ5KjyPvr8C9sAxmPtZfGsQVKCi4n8ShxP9BkbDdbtjtA9aumNybAZ1BxC\",\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.RegisterInboundAsync(new TravelRuleInboundRequest\n{\n    Chain = \"ETH\",\n    Txid = \"0xdeposit-hash\",\n    WalletAddress = \"0xYourDepositWallet\",\n    Amount = \"500.00\",\n    Currency = \"USDC\",\n    OriginatorData = new Dictionary<string, object> { [\"name\"] = \"Origin CASP SL\" },\n    BeneficiaryData = new Dictionary<string, object> { [\"name\"] = \"Ana Diaz\" },\n    OriginatingVasp = new TravelRuleInboundRequestOriginatingVasp\n    {\n        Name = \"Origin CASP SL\",\n        Lei = \"\",\n        TravelAddress = \"ta9JbXbsBSuS5ozArJRFVgvBHMVnDGUnrPPChSZYQsuZTn3kPrJXUQ7RSLUEJ5KjyPvr8C9sAxmPtZfGsQVKCi4n8ShxP9BkbDdbtjtA9aumNybAZ1BxC\",\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Un transfert pour ce txid et cette adresse était déjà enregistré ; l'existant est renvoyé inchangé (created vaut false).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleInboundResponse"
                }
              }
            }
          },
          "201": {
            "description": "Un nouveau transfert Travel Rule a été enregistré, sur une nouvelle transaction entrante ou sur un dépôt non réclamé existant (created vaut true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleInboundResponse"
                }
              }
            }
          },
          "400": {
            "description": "Un champ obligatoire (`chain`, `txid`, `wallet_address`, `amount`, `currency`) est manquant, `originating_vasp.lei` n'est pas un LEI valide, `originating_vasp.travel_address` n'est pas une Travel Address valide, un mémo, une X-address ou un `utxo` que la blockchain ne peut pas porter, ou `originator_data` / `beneficiary_data` n'est pas un objet.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing field": {
                    "value": {
                      "txid": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid LEI": {
                    "value": {
                      "originating_vasp": {
                        "lei": [
                          "Invalid LEI: expected 20 alphanumeric characters (ISO 17442)."
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/test-vasp/inbound/": {
      "post": {
        "summary": "Déclencher un transfert entrant depuis le Didit Test VASP (sandbox)",
        "description": "Applications en sandbox uniquement. Le Didit Test VASP envoie à votre application un transfert Travel Rule entrant, afin que vous puissiez tester le côté réception d'un échange de bout en bout avant le passage en production. Le transfert est enregistré et fait l'objet d'une décision selon la même logique qu'un véritable transfert entrant provenant d'un réseau par rapport à votre carnet d'adresses de portefeuilles, de sorte que la boîte de réception, la décision et le flux de propriété du portefeuille se comportent comme en production. Rien ne quitte Didit. Une application en production reçoit une erreur 400. Renvoyez la même `reference` pour obtenir le transfert enregistré lors du premier appel au lieu d'en créer un second.",
        "operationId": "triggerTravelRuleTestVaspInbound",
        "x-didit-sdk": {
          "resource": "transactions.travel_rule",
          "method": "trigger_test_vasp_inbound",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleTestVaspInboundRequest"
              },
              "example": {
                "beneficiary_wallet_address": "0xYourSandboxWallet",
                "scenario": "accept",
                "amount": "1",
                "reference": "demo-001"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/test-vasp/inbound/ \\\n  -H 'x-api-key: YOUR_SANDBOX_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"beneficiary_wallet_address\":\"0xYourSandboxWallet\",\"scenario\":\"accept\",\"reference\":\"demo-001\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.travel_rule.trigger_test_vasp_inbound(\n    beneficiary_wallet_address=\"0xYourSandboxWallet\",\n    scenario=\"accept\",\n    amount=\"1\",\n    reference=\"demo-001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.travelRule.triggerTestVaspInbound({\n  beneficiary_wallet_address: \"0xYourSandboxWallet\",\n  scenario: \"accept\",\n  amount: \"1\",\n  reference: \"demo-001\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.TravelRule.TriggerTestVASPInbound(ctx, didit.TravelRuleTestVASPInboundRequest{\n\tBeneficiaryWalletAddress: \"0xYourSandboxWallet\",\n\tScenario:                 didit.Some(didit.TravelRuleTestVASPInboundRequestScenario(\"accept\")),\n\tAmount:                   didit.String(\"1\"),\n\tReference:                didit.String(\"demo-001\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleTestVaspInboundRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().travelRule().triggerTestVaspInbound(TravelRuleTestVaspInboundRequest.builder()\n        .beneficiaryWalletAddress(\"0xYourSandboxWallet\")\n        .scenario(TravelRuleTestVaspInboundRequest.Scenario.of(\"accept\"))\n        .amount(\"1\")\n        .reference(\"demo-001\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->travelRule->triggerTestVaspInbound([\n    'beneficiary_wallet_address' => '0xYourSandboxWallet',\n    'scenario' => 'accept',\n    'amount' => '1',\n    'reference' => 'demo-001',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.travel_rule.trigger_test_vasp_inbound(\n  beneficiary_wallet_address: \"0xYourSandboxWallet\",\n  scenario: \"accept\",\n  amount: \"1\",\n  reference: \"demo-001\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.TravelRule.TriggerTestVaspInboundAsync(new TravelRuleTestVaspInboundRequest\n{\n    BeneficiaryWalletAddress = \"0xYourSandboxWallet\",\n    Scenario = new TravelRuleTestVaspInboundRequestScenario(\"accept\"),\n    Amount = \"1\",\n    Reference = \"demo-001\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Le transfert entrant a été enregistré et a fait l'objet d'une décision. Une nouvelle requête avec la même `reference` renvoie le même corps.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleTestVaspInboundResponse"
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide, `scenario` inconnu ou non pris en charge, ou l'application est en environnement de production.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "409": {
            "description": "Le transfert n'a pas pu être enregistré, par exemple parce que Travel Rule n'est pas activé pour l'application.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/widget-session/": {
      "post": {
        "summary": "Émettre une session de widget de propriété du portefeuille",
        "description": "Générer une URL/un token de widget hébergé de contrôle de portefeuille. Redirigez le client vers l'URL renvoyée pour prouver le contrôle d'un portefeuille (signature de message, test Satoshi, capture d'écran ou autodéclaration). Le widget est uniquement disponible sur le web dans cette version - ouvrez l'URL dans le navigateur système ou un onglet personnalisé, jamais dans une webview de SDK mobile.",
        "operationId": "createTravelRuleWidgetSession",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "create_widget_session",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleWidgetSessionCreate"
              },
              "example": {
                "wallet_address": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9",
                "chain": "ETH",
                "holder_name": "Jane Doe",
                "vendor_data": "user-042",
                "transaction_id": "99999999-aaaa-bbbb-cccc-dddddddddddd",
                "expires_in_minutes": 60
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/widget-session/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"wallet_address\":\"0xd3b62acb76fb27a7f8961ec40fa11746b113aca9\",\"chain\":\"ETH\",\"holder_name\":\"Jane Doe\",\"transaction_id\":\"99999999-aaaa-bbbb-cccc-dddddddddddd\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.create_widget_session(\n    wallet_address=\"0xd3b62acb76fb27a7f8961ec40fa11746b113aca9\",\n    chain=\"ETH\",\n    holder_name=\"Jane Doe\",\n    vendor_data=\"user-042\",\n    transaction_id=\"99999999-aaaa-bbbb-cccc-dddddddddddd\",\n    expires_in_minutes=60,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.createWidgetSession({\n  wallet_address: \"0xd3b62acb76fb27a7f8961ec40fa11746b113aca9\",\n  chain: \"ETH\",\n  holder_name: \"Jane Doe\",\n  vendor_data: \"user-042\",\n  transaction_id: \"99999999-aaaa-bbbb-cccc-dddddddddddd\",\n  expires_in_minutes: 60,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.CreateWidgetSession(ctx, didit.TravelRuleWidgetSessionCreate{\n\tWalletAddress:    didit.String(\"0xd3b62acb76fb27a7f8961ec40fa11746b113aca9\"),\n\tChain:            didit.String(\"ETH\"),\n\tHolderName:       didit.String(\"Jane Doe\"),\n\tVendorData:       didit.String(\"user-042\"),\n\tTransactionID:    didit.String(\"99999999-aaaa-bbbb-cccc-dddddddddddd\"),\n\tExpiresInMinutes: didit.Int(60),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleWidgetSessionCreate;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().createWidgetSession(TravelRuleWidgetSessionCreate.builder()\n        .walletAddress(\"0xd3b62acb76fb27a7f8961ec40fa11746b113aca9\")\n        .chain(\"ETH\")\n        .holderName(\"Jane Doe\")\n        .vendorData(\"user-042\")\n        .transactionId(\"99999999-aaaa-bbbb-cccc-dddddddddddd\")\n        .expiresInMinutes(60L)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->createWidgetSession([\n    'wallet_address' => '0xd3b62acb76fb27a7f8961ec40fa11746b113aca9',\n    'chain' => 'ETH',\n    'holder_name' => 'Jane Doe',\n    'vendor_data' => 'user-042',\n    'transaction_id' => '99999999-aaaa-bbbb-cccc-dddddddddddd',\n    'expires_in_minutes' => 60,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.create_widget_session(\n  wallet_address: \"0xd3b62acb76fb27a7f8961ec40fa11746b113aca9\",\n  chain: \"ETH\",\n  holder_name: \"Jane Doe\",\n  vendor_data: \"user-042\",\n  transaction_id: \"99999999-aaaa-bbbb-cccc-dddddddddddd\",\n  expires_in_minutes: 60\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.CreateWidgetSessionAsync(new TravelRuleWidgetSessionCreate\n{\n    WalletAddress = \"0xd3b62acb76fb27a7f8961ec40fa11746b113aca9\",\n    Chain = \"ETH\",\n    HolderName = \"Jane Doe\",\n    VendorData = \"user-042\",\n    TransactionId = \"99999999-aaaa-bbbb-cccc-dddddddddddd\",\n    ExpiresInMinutes = 60,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "La session de widget générée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetSessionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide : `callback_url` n'est pas une URL http(s) absolue, `expires_in_minutes` n'est pas compris entre 5 et 10080, `transaction_id` n'est pas un UUID, ou un champ dépasse sa limite.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid callback_url": {
                    "value": {
                      "callback_url": [
                        "callback_url must be an absolute http(s) URL."
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`transaction_id` ne désigne pas un transfert Travel Rule dans cette application."
          }
        }
      }
    },
    "/v3/travel-rule/widget/{token}/": {
      "get": {
        "summary": "Obtenir le contexte du widget de propriété du portefeuille",
        "description": "Endpoint public de lecture indexé par le token de session du widget - aucune clé API requise. Renvoie le contexte du widget ainsi que le statut de chaque preuve, afin que vous puissiez l'interroger pour détecter son achèvement ; completed_at devient non nul dès qu'une preuve est vérifiée. Une preuve SATOSHI_TEST peut rester au statut PENDING tant que son dépôt est détecté on-chain mais non confirmé - une tâche de fond la revérifie automatiquement et la valide dès que le dépôt est confirmé, aucune action du client n'est donc requise pendant cette attente. Chaque preuve inclut les champs nécessaires à sa méthode : deposit_address, expected_amount et son propre expires_at pour SATOSHI_TEST ; challenge pour MESSAGE_SIGNING. Privilégiez le webhook travel_rule.status.updated au lieu de requêtes répétées lorsque la session est liée à un transfert.",
        "operationId": "getTravelRuleWidgetContext",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "retrieve_widget_context",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "Token de session opaque renvoyé lors de la création de la session du widget.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://verification.didit.me/v3/travel-rule/widget/{token}/"
          }
        ],
        "responses": {
          "200": {
            "description": "Le contexte du widget et les statuts des preuves.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetContext"
                }
              }
            }
          },
          "404": {
            "description": "Token inconnu."
          },
          "410": {
            "description": "La session a expiré sans être menée à son terme."
          }
        }
      }
    },
    "/v3/travel-rule/widget/{token}/vasps/": {
      "get": {
        "summary": "Rechercher des VASP depuis le widget de portefeuille",
        "description": "Endpoint public de lecture indexé par le token de session du widget, aucune clé API requise : le sélecteur de VASP du widget de l'utilisateur final. Même recherche et mêmes filtres que GET /v3/travel-rule/vasps/ pour l'application du widget, indiquant uniquement l'identité de chaque VASP et s'il est joignable.",
        "operationId": "listTravelRuleWidgetVasps",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "list_widget_vasps",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "Token de session opaque renvoyé lors de la création de la session du widget.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 255
            },
            "description": "Un fragment de nom ou d'alias (insensible à la casse), un LEI exact ou un domaine (example.com ou une URL sur celui-ci). Les membres du réseau Didit correspondent selon leur dénomination sociale, leur LEI ou le domaine de leur e-mail de conformité."
          },
          {
            "name": "network",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "GTR",
                "TRUST",
                "VERIFYVASP",
                "SYGNA",
                "TRISA"
              ]
            },
            "description": "Uniquement les entrées de l'annuaire actuellement répertoriées dans l'annuaire des membres d'un réseau."
          },
          {
            "name": "jurisdiction",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Code pays ISO 3166 alpha-2 ou alpha-3. 400 pour toute autre valeur."
          },
          {
            "name": "reachable",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "true : uniquement les VASP vers lesquels votre application dispose d'un itinéraire disponible (membres du réseau Didit inclus). false : uniquement les entrées de l'annuaire qu'elle ne peut pas joindre aujourd'hui."
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "directory",
                "didit"
              ]
            },
            "description": "Uniquement les entrées de l'annuaire, ou uniquement les membres du réseau Didit."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl 'https://verification.didit.me/v3/travel-rule/widget/{token}/vasps/?search=counterparty'"
          }
        ],
        "responses": {
          "200": {
            "description": "Résultats paginés, triés par nom.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/VaspDirectoryWidgetEntry"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Un filtre n'est pas valide : le corps indique chaque champ, par exemple un réseau ou un code pays inconnu.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "jurisdiction": [
                    "Use an ISO 3166 alpha-2 or alpha-3 country code."
                  ],
                  "network": [
                    "\"SWIFT\" is not a valid choice."
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Token inconnu."
          },
          "410": {
            "description": "La session a expiré."
          }
        }
      },
      "post": {
        "summary": "Sélectionner le VASP de la contrepartie dans le widget de portefeuille",
        "description": "Endpoint public d'écriture indexé par le token de session du widget, aucune clé API requise : l'utilisateur final a choisi le VASP de destination que la détection automatique n'a pas pu identifier. Seul un transfert sortant avec le statut COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA est accepté. Le transfert est acheminé vers ce VASP et envoyé à nouveau ; la détection automatique ne remplace jamais ce choix.",
        "operationId": "selectTravelRuleWidgetVasp",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "select_widget_vasp",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "Token de session opaque renvoyé lors de la création de la session du widget.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "vasp"
                ],
                "properties": {
                  "vasp": {
                    "type": "string",
                    "format": "uuid",
                    "description": "L'`id` d'un VASP provenant de `GET /v3/travel-rule/widget/{token}/vasps/`."
                  }
                }
              },
              "example": {
                "vasp": "9f1c2b34-5d6e-4f70-8a91-b2c3d4e5f607"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/widget/{token}/vasps/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"vasp\": \"9f1c2b34-5d6e-4f70-8a91-b2c3d4e5f607\"}'"
          }
        ],
        "responses": {
          "200": {
            "description": "Le choix a été enregistré et le transfert est renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "transfer_status": {
                      "type": "string",
                      "description": "Le statut du transfert après la sélection."
                    },
                    "counterparty_vasp": {
                      "type": "string",
                      "description": "Le nom du VASP choisi par l'utilisateur final."
                    }
                  }
                },
                "example": {
                  "detail": "Counterparty VASP selected; the transfer is being resent.",
                  "transfer_status": "AWAITING_COUNTERPARTY",
                  "counterparty_vasp": "Northwind Exchange"
                }
              }
            }
          },
          "400": {
            "description": "`vasp` est manquant, ou aucune entrée de répertoire active ne possède cet identifiant.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "vasp": [
                    "No directory entry has this id."
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Token inconnu."
          },
          "409": {
            "description": "La session du widget n'est pas liée à un transfert Travel Rule, ou le transfert n'est pas un transfert sortant dans un statut qui accepte une contrepartie."
          },
          "410": {
            "description": "La session a expiré."
          }
        }
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/vendor-users/toggle-ongoing-monitoring/": {
      "patch": {
        "summary": "Activer ou désactiver la surveillance AML continue pour les utilisateurs",
        "description": "Active ou désactive la surveillance AML continue au niveau de l'utilisateur. Exactement un filtrage AML surveillé est conservé par utilisateur ; pour les utilisateurs sans aucun filtrage AML (par exemple les utilisateurs importés), un filtrage AML est d'abord créé et effectué, facturé comme un filtrage AML standard. Définissez estimate_only pour prévisualiser les nombres et les coûts sans effectuer d'écriture. Les lots de 20 ou moins se résolvent de manière synchrone (200, COMPLETED) ; les lots plus importants renvoient 202 et s'exécutent de manière asynchrone.",
        "operationId": "toggle_vendor_users_ongoing_monitoring",
        "x-didit-sdk": {
          "resource": "users",
          "method": "set_ongoing_monitoring",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OngoingMonitoringToggleRequest"
              },
              "example": {
                "is_enabled": true,
                "didit_internal_id_list": [
                  "5b9a0000-0000-4000-8000-00000000f00d"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estimation (lorsque estimate_only) ou tâche terminée pour les petits lots traités en mode inline.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringToggleResult"
                }
              }
            }
          },
          "202": {
            "description": "Les lots plus volumineux sont traités de manière asynchrone ; interrogez l'endpoint du job à l'aide du job_id renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringJob"
                }
              }
            }
          },
          "403": {
            "description": "Privilège write:sessions manquant, ou solde insuffisant pour activer (l'estimation est incluse dans le corps de l'erreur)."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.users.set_ongoing_monitoring(\n    is_enabled=True,\n    didit_internal_id_list=[\"5b9a0000-0000-4000-8000-00000000f00d\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.users.setOngoingMonitoring({\n  is_enabled: true,\n  didit_internal_id_list: [\"5b9a0000-0000-4000-8000-00000000f00d\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Users.SetOngoingMonitoring(ctx, didit.OngoingMonitoringToggleRequest{\n\tIsEnabled:           true,\n\tDiditInternalIDList: didit.Some([]string{\"5b9a0000-0000-4000-8000-00000000f00d\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.OngoingMonitoringToggleRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.users().setOngoingMonitoring(OngoingMonitoringToggleRequest.builder()\n        .isEnabled(true)\n        .diditInternalIdList(List.of(\"5b9a0000-0000-4000-8000-00000000f00d\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->users->setOngoingMonitoring([\n    'is_enabled' => true,\n    'didit_internal_id_list' => ['5b9a0000-0000-4000-8000-00000000f00d'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.users.set_ongoing_monitoring(\n  is_enabled: true,\n  didit_internal_id_list: [\"5b9a0000-0000-4000-8000-00000000f00d\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Users.SetOngoingMonitoringAsync(new OngoingMonitoringToggleRequest\n{\n    IsEnabled = true,\n    DiditInternalIdList = new string[] { \"5b9a0000-0000-4000-8000-00000000f00d\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/vendor-users/toggle-ongoing-monitoring/{job_id}/": {
      "get": {
        "summary": "Obtenir une tâche de surveillance AML continue",
        "description": "Progression et compteurs par résultat d'un travail de basculement de la surveillance. Interrogez toutes les deux secondes tant que le statut est PENDING ou PROCESSING.",
        "operationId": "get_vendor_users_ongoing_monitoring_job",
        "x-didit-sdk": {
          "resource": "users",
          "method": "retrieve_ongoing_monitoring_job",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de la tâche de surveillance renvoyé par l'endpoint d'activation/désactivation."
          }
        ],
        "responses": {
          "200": {
            "description": "La tâche.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringJob"
                }
              }
            }
          },
          "404": {
            "description": "Tâche inconnue pour cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.users.retrieve_ongoing_monitoring_job(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.users.retrieveOngoingMonitoringJob(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Users.RetrieveOngoingMonitoringJob(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.users().retrieveOngoingMonitoringJob(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->users->retrieveOngoingMonitoringJob('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.users.retrieve_ongoing_monitoring_job(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Users.RetrieveOngoingMonitoringJobAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/vendor-businesses/toggle-ongoing-monitoring/": {
      "patch": {
        "summary": "Activer ou désactiver la surveillance AML continue pour les entreprises",
        "description": "Équivalent au niveau de l'entreprise de la bascule utilisateur : un filtrage AML surveillé par entreprise, les entreprises ne disposant d'aucun filtrage AML étant filtrées en premier (entité morale). Mêmes modalités d'estimate_only, de chemin rapide inline et de tâche asynchrone.",
        "operationId": "toggle_vendor_businesses_ongoing_monitoring",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "set_ongoing_monitoring",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OngoingMonitoringToggleRequest"
              },
              "example": {
                "is_enabled": true,
                "didit_internal_id_list": [
                  "b0000000-0000-4000-8000-0000000000b1"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estimation (lorsque estimate_only) ou tâche terminée pour les petits lots traités en mode inline.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringToggleResult"
                }
              }
            }
          },
          "202": {
            "description": "Les lots plus volumineux sont traités de manière asynchrone ; interrogez l'endpoint du job à l'aide du job_id renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringJob"
                }
              }
            }
          },
          "403": {
            "description": "Privilège write:sessions manquant, ou solde insuffisant pour activer (l'estimation est incluse dans le corps de l'erreur)."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.businesses.set_ongoing_monitoring(\n    is_enabled=True,\n    didit_internal_id_list=[\"b0000000-0000-4000-8000-0000000000b1\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.businesses.setOngoingMonitoring({\n  is_enabled: true,\n  didit_internal_id_list: [\"b0000000-0000-4000-8000-0000000000b1\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.SetOngoingMonitoring(ctx, didit.OngoingMonitoringToggleRequest{\n\tIsEnabled:           true,\n\tDiditInternalIDList: didit.Some([]string{\"b0000000-0000-4000-8000-0000000000b1\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.OngoingMonitoringToggleRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.businesses().setOngoingMonitoring(OngoingMonitoringToggleRequest.builder()\n        .isEnabled(true)\n        .diditInternalIdList(List.of(\"b0000000-0000-4000-8000-0000000000b1\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->businesses->setOngoingMonitoring([\n    'is_enabled' => true,\n    'didit_internal_id_list' => ['b0000000-0000-4000-8000-0000000000b1'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.businesses.set_ongoing_monitoring(\n  is_enabled: true,\n  didit_internal_id_list: [\"b0000000-0000-4000-8000-0000000000b1\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.SetOngoingMonitoringAsync(new OngoingMonitoringToggleRequest\n{\n    IsEnabled = true,\n    DiditInternalIdList = new string[] { \"b0000000-0000-4000-8000-0000000000b1\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/vendor-businesses/toggle-ongoing-monitoring/{job_id}/": {
      "get": {
        "summary": "Obtenir une tâche de surveillance AML continue",
        "description": "Progression et compteurs par résultat d'un travail de basculement de la surveillance. Interrogez toutes les deux secondes tant que le statut est PENDING ou PROCESSING.",
        "operationId": "get_vendor_businesses_ongoing_monitoring_job",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "retrieve_ongoing_monitoring_job",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de la tâche de surveillance renvoyé par l'endpoint d'activation/désactivation."
          }
        ],
        "responses": {
          "200": {
            "description": "La tâche.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringJob"
                }
              }
            }
          },
          "404": {
            "description": "Tâche inconnue pour cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.businesses.retrieve_ongoing_monitoring_job(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.businesses.retrieveOngoingMonitoringJob(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.RetrieveOngoingMonitoringJob(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.businesses().retrieveOngoingMonitoringJob(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->businesses->retrieveOngoingMonitoringJob('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.businesses.retrieve_ongoing_monitoring_job(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.RetrieveOngoingMonitoringJobAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/businesses/toggle-ongoing-monitoring/": {
      "patch": {
        "summary": "Activer ou désactiver la surveillance AML continue pour les sessions d'entreprise",
        "description": "Bascule au niveau de la session pour les vérifications KYB, identifiée par le numéro de session. Les sessions sans filtrage AML en reçoivent un qui est créé et rattaché à la session elle-même. Même contrat pour estimate_only, le fast-path inline et la tâche asynchrone que pour les endpoints au niveau utilisateur. Remplace le comportement synchrone hérité qui ignorait les sessions sans filtrage AML.",
        "operationId": "toggle_business_sessions_ongoing_monitoring",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "set_session_ongoing_monitoring",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "is_enabled"
                ],
                "properties": {
                  "is_enabled": {
                    "type": "boolean",
                    "description": "true pour activer la surveillance, false pour la désactiver."
                  },
                  "estimate_only": {
                    "type": "boolean",
                    "default": false,
                    "description": "Si true, renvoie l'estimation des coûts et n'effectue aucune écriture."
                  },
                  "update_all": {
                    "type": "boolean",
                    "default": false,
                    "description": "S'applique à chaque entité de l'application (restreint par les paramètres filter_* lorsqu'ils sont présents)."
                  },
                  "filter_search": {
                    "type": "string"
                  },
                  "filter_status": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "filter_country": {
                    "type": "string"
                  },
                  "filter_date_from": {
                    "type": "string",
                    "format": "date"
                  },
                  "filter_date_to": {
                    "type": "string",
                    "format": "date"
                  },
                  "session_numbers": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Numéros de session entreprise à basculer. Requis sauf si update_all (ou l'ancien alias toggle_all) vaut true."
                  },
                  "toggle_all": {
                    "type": "boolean",
                    "default": false,
                    "description": "Alias obsolète de update_all."
                  },
                  "filter_workflow_id": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "is_enabled": true,
                "session_numbers": [
                  "1001",
                  "1002"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estimation (lorsque estimate_only) ou tâche terminée pour les petits lots traités en mode inline.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringToggleResult"
                }
              }
            }
          },
          "202": {
            "description": "Les lots plus volumineux sont traités de manière asynchrone ; interrogez l'endpoint du job à l'aide du job_id renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringJob"
                }
              }
            }
          },
          "403": {
            "description": "Privilège write:sessions manquant, ou solde insuffisant pour activer (l'estimation est incluse dans le corps de l'erreur)."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.businesses.set_session_ongoing_monitoring(\n    is_enabled=True,\n    session_numbers=[\"1001\", \"1002\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.businesses.setSessionOngoingMonitoring({\n  is_enabled: true,\n  session_numbers: [\"1001\", \"1002\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.SetSessionOngoingMonitoring(ctx, didit.BusinessesSetSessionOngoingMonitoringParams{\n\tIsEnabled:      true,\n\tSessionNumbers: didit.Some([]string{\"1001\", \"1002\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.BusinessesSetSessionOngoingMonitoringParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.businesses().setSessionOngoingMonitoring(BusinessesSetSessionOngoingMonitoringParams.builder()\n        .isEnabled(true)\n        .sessionNumbers(List.of(\"1001\", \"1002\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->businesses->setSessionOngoingMonitoring([\n    'is_enabled' => true,\n    'session_numbers' => ['1001', '1002'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.businesses.set_session_ongoing_monitoring(\n  is_enabled: true,\n  session_numbers: [\"1001\", \"1002\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.SetSessionOngoingMonitoringAsync(new BusinessesSetSessionOngoingMonitoringParams\n{\n    IsEnabled = true,\n    SessionNumbers = new string[] { \"1001\", \"1002\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/businesses/toggle-ongoing-monitoring/{job_id}/": {
      "get": {
        "summary": "Obtenir une tâche de surveillance AML continue",
        "description": "Progression et compteurs par résultat d'un travail de basculement de la surveillance. Interrogez toutes les deux secondes tant que le statut est PENDING ou PROCESSING.",
        "operationId": "get_business_sessions_ongoing_monitoring_job",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "retrieve_session_ongoing_monitoring_job",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de la tâche de surveillance renvoyé par l'endpoint d'activation/désactivation."
          }
        ],
        "responses": {
          "200": {
            "description": "La tâche.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OngoingMonitoringJob"
                }
              }
            }
          },
          "404": {
            "description": "Tâche inconnue pour cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.businesses.retrieve_session_ongoing_monitoring_job(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.businesses.retrieveSessionOngoingMonitoringJob(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.RetrieveSessionOngoingMonitoringJob(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.businesses().retrieveSessionOngoingMonitoringJob(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->businesses->retrieveSessionOngoingMonitoringJob('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.businesses.retrieve_session_ongoing_monitoring_job(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.RetrieveSessionOngoingMonitoringJobAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/": {
      "get": {
        "summary": "Lister les dossiers",
        "description": "Lister les dossiers pour l'application, les plus récents en premier. Prend en charge le filtrage, la recherche et le tri ; voir les paramètres de requête. Paginé avec `limit`/`offset`.",
        "operationId": "list_cases",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            },
            "description": "Taille de page. Vaut 50 par défaut."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            },
            "description": "Décalage de départ (base zéro) du premier enregistrement."
          },
          {
            "name": "status__in",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Statuts à inclure séparés par des virgules, par exemple OPEN,AWAITING_USER."
          },
          {
            "name": "priority",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Priorités à inclure séparées par des virgules."
          },
          {
            "name": "source__in",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Sources à inclure séparées par des virgules."
          },
          {
            "name": "blueprint",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filtrer selon les dossiers associés à ce blueprint."
          },
          {
            "name": "assigned_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filtrer selon les dossiers assignés à cet utilisateur."
          },
          {
            "name": "unassigned",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "true pour les dossiers non attribués, false pour les dossiers attribués."
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrer selon les dossiers portant exactement ce tag."
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Correspond à title, case_number, tag, nom/UUID/identifiant externe du sujet, UUID de la session liée, ou UUID de la transaction liée."
          },
          {
            "name": "date_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Limite inférieure de la date de création (incluse)."
          },
          {
            "name": "date_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Limite supérieure de la date de création (incluse)."
          },
          {
            "name": "due_before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Limite supérieure de due_at."
          },
          {
            "name": "overdue",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "true pour ne renvoyer que les dossiers en retard ouverts/en attente de l'utilisateur."
          },
          {
            "name": "ordering",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "-created_at",
                "due_at",
                "-due_at"
              ],
              "default": "-created_at"
            },
            "description": "Ordre de tri. due_at place les valeurs nulles en dernier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/?status__in=OPEN,AWAITING_USER&ordering=-due_at' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.ListAutoPaging(ctx, didit.CasesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginée des dossiers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de lignes correspondantes. Exact jusqu'à 100, plafonné à 100 au-delà pour des raisons de performance. Fiez-vous à la valeur null de `next` pour détecter la dernière page."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou null."
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou null."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaseListItem"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer un dossier",
        "description": "Créez un dossier rattaché à exactement un sujet (un utilisateur ou une entreprise), directement ou en déduisant le sujet à partir d'un lien de session ou de transaction joint. La source est toujours `MANUAL` pour les dossiers créés par API.",
        "operationId": "create_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "blueprint": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "UUID du CaseBlueprint. Omettez pour n'utiliser aucun modèle."
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "LOW",
                      "MEDIUM",
                      "HIGH"
                    ],
                    "default": "MEDIUM"
                  },
                  "due_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "subject": {
                    "type": "object",
                    "description": "Requis sauf si links est fourni ; le sujet unique du dossier.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "user",
                          "business"
                        ]
                      },
                      "uuid": {
                        "type": "string",
                        "format": "uuid"
                      }
                    }
                  },
                  "links": {
                    "type": "array",
                    "description": "Sessions, sessions d'entreprise ou transactions à associer lors de la création, par ex. [{\"entity_type\": \"transaction\", \"entity_uuid\": \"...\"}]. Lorsque subject est omis, le sujet est déduit du propriétaire du premier lien.",
                    "items": {
                      "type": "object"
                    }
                  },
                  "assigned_to": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "UUID de l'utilisateur à attribuer immédiatement."
                  },
                  "review_duplicates": {
                    "type": "boolean",
                    "default": false,
                    "description": "Revérifier les enquêtes existantes avant de créer le dossier. Lorsque cette valeur est vraie, un sujet ayant des dossiers existants requiert un champ separate_incident_reason non vide. La console active toujours cette protection. L'omettre préserve le comportement actuel de l'API."
                  },
                  "separate_incident_reason": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "source_context": {
                    "$ref": "#/components/schemas/CaseDuplicateCaseFraudSourceContextRequest"
                  }
                }
              },
              "example": {
                "title": "Manual - Jane Doe",
                "blueprint": "b1de0000-0000-4000-8000-000000000002",
                "priority": "HIGH",
                "subject": {
                  "type": "user",
                  "uuid": "5b9a0000-0000-4000-8000-00000000f00d"
                },
                "tags": [
                  "review"
                ]
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"title\": \"Manual - Jane Doe\", \"blueprint\": \"b1de0000-0000-4000-8000-000000000002\", \"priority\": \"HIGH\", \"subject\": {\"type\": \"user\", \"uuid\": \"5b9a0000-0000-4000-8000-00000000f00d\"}, \"tags\": [\"review\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.create(\n    title=\"Manual - Jane Doe\",\n    blueprint=\"b1de0000-0000-4000-8000-000000000002\",\n    priority=\"HIGH\",\n    tags=[\"review\"],\n    subject={\n        \"type\": \"user\",\n        \"uuid\": \"5b9a0000-0000-4000-8000-00000000f00d\",\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.create({\n  title: \"Manual - Jane Doe\",\n  blueprint: \"b1de0000-0000-4000-8000-000000000002\",\n  priority: \"HIGH\",\n  tags: [\"review\"],\n  subject: {\n    type: \"user\",\n    uuid: \"5b9a0000-0000-4000-8000-00000000f00d\",\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Create(ctx, didit.CasesCreateParams{\n\tTitle:     \"Manual - Jane Doe\",\n\tBlueprint: didit.String(\"b1de0000-0000-4000-8000-000000000002\"),\n\tPriority:  didit.Some(didit.CasesCreateParamsPriority(\"HIGH\")),\n\tTags:      didit.Some([]string{\"review\"}),\n\tSubject: didit.Some(didit.CasesCreateParamsSubject{\n\t\tType: didit.Some(didit.CasesCreateParamsSubjectType(\"user\")),\n\t\tUUID: didit.String(\"5b9a0000-0000-4000-8000-00000000f00d\"),\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.CasesCreateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().create(CasesCreateParams.builder()\n        .title(\"Manual - Jane Doe\")\n        .blueprint(\"b1de0000-0000-4000-8000-000000000002\")\n        .priority(CasesCreateParams.Priority.of(\"HIGH\"))\n        .tags(List.of(\"review\"))\n        .subject(CasesCreateParams.Subject.builder()\n                .type(CasesCreateParams.Subject.Type.of(\"user\"))\n                .uuid(\"5b9a0000-0000-4000-8000-00000000f00d\")\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->create([\n    'title' => 'Manual - Jane Doe',\n    'blueprint' => 'b1de0000-0000-4000-8000-000000000002',\n    'priority' => 'HIGH',\n    'tags' => ['review'],\n    'subject' => [\n        'type' => 'user',\n        'uuid' => '5b9a0000-0000-4000-8000-00000000f00d',\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.create(\n  title: \"Manual - Jane Doe\",\n  blueprint: \"b1de0000-0000-4000-8000-000000000002\",\n  priority: \"HIGH\",\n  tags: [\"review\"],\n  subject: {\n    type: \"user\",\n    uuid: \"5b9a0000-0000-4000-8000-00000000f00d\",\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.CreateAsync(new CasesCreateParams\n{\n    Title = \"Manual - Jane Doe\",\n    Blueprint = \"b1de0000-0000-4000-8000-000000000002\",\n    Priority = new CasesCreateParamsPriority(\"HIGH\"),\n    Tags = new string[] { \"review\" },\n    Subject = new CasesCreateParamsSubject\n    {\n        Type = new CasesCreateParamsSubjectType(\"user\"),\n        Uuid = \"5b9a0000-0000-4000-8000-00000000f00d\",\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Dossier créé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          },
          "400": {
            "description": "Ni subject ni links n'ont été fournis, ou l'objet/modèle/assigné n'a pas été trouvé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "409": {
            "description": "L'examen des doublons est activé et un dossier existant a été trouvé sans motif d'incident distinct. Aucun dossier n'a été créé."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/": {
      "get": {
        "summary": "Obtenir le dossier",
        "description": "Récupérer un dossier avec son sujet, son modèle, ses notes, ses événements, ses liens et sa checklist.",
        "operationId": "get_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "retrieve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.retrieve(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.retrieve(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Retrieve(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().retrieve(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->retrieve('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.retrieve(\"c1a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RetrieveAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détail du dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          },
          "404": {
            "description": "Dossier (ou ressource imbriquée) introuvable dans cette application.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour le dossier",
        "description": "Mettre à jour le titre, la priorité, la date d'échéance, les tags ou l'équipe d'examen responsable du dossier. Envoyez uniquement les champs que vous souhaitez modifier ; les champs omis conservent leur valeur. `tags` remplace la liste complète des tags. `team` prend l'uuid d'une équipe d'examen active de cette application (listez-les avec `GET .../cases/teams/`), ou null pour retirer l'équipe. Nécessite une clé API à accès complet, ou `write:cases` pour un membre de la console : une clé avec un accès restreint renvoie 403. Enregistre les événements PRIORITY_CHANGED, DUE_DATE_CHANGED, TAG_ADDED, TAG_REMOVED et TEAM_CHANGED le cas échéant ; un changement de titre est enregistré sans événement dans l'historique. Renvoie le dossier mis à jour.",
        "operationId": "update_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "update",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nouveau titre du dossier."
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "LOW",
                      "MEDIUM",
                      "HIGH"
                    ]
                  },
                  "due_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true,
                    "description": "Nouvelle date limite. Envoyez null pour l'effacer."
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "La liste complète des tags. Elle remplace les tags actuels."
                  },
                  "team": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "UUID de l'équipe de révision propriétaire du dossier. Il doit s'agir d'une équipe active de cette application. Envoyez null pour effacer l'équipe."
                  }
                }
              },
              "examples": {
                "Change priority and deadline": {
                  "value": {
                    "priority": "HIGH",
                    "due_at": "2026-11-01T00:00:00Z"
                  }
                },
                "Move the case to a team": {
                  "value": {
                    "team": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
                  }
                },
                "Clear the team": {
                  "value": {
                    "team": null
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"priority\": \"HIGH\", \"due_at\": \"2026-08-01T00:00:00Z\"}'"
          },
          {
            "lang": "curl",
            "label": "curl (change team)",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"team\": \"3fa85f64-5717-4562-b3fc-2c963f66afa6\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.update(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    priority=\"HIGH\",\n    due_at=\"2026-11-01T00:00:00Z\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.update(\"c1a5e000-0000-4000-8000-000000000001\", {\n  priority: \"HIGH\",\n  due_at: \"2026-11-01T00:00:00Z\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Update(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesUpdateParams{\n\tPriority: didit.Some(didit.CasesUpdateParamsPriority(\"HIGH\")),\n\tDueAt:    didit.Time(time.Date(2026, 11, 1, 0, 0, 0, 0, time.UTC)),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.OffsetDateTime;\nimport me.didit.Didit;\nimport me.didit.types.CasesUpdateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().update(\"c1a5e000-0000-4000-8000-000000000001\", CasesUpdateParams.builder()\n        .priority(CasesUpdateParams.Priority.of(\"HIGH\"))\n        .dueAt(OffsetDateTime.parse(\"2026-11-01T00:00:00Z\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->update('c1a5e000-0000-4000-8000-000000000001', [\n    'priority' => 'HIGH',\n    'due_at' => '2026-11-01T00:00:00Z',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.update(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  priority: \"HIGH\",\n  due_at: \"2026-11-01T00:00:00Z\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.UpdateAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesUpdateParams\n{\n    Priority = new CasesUpdateParamsPriority(\"HIGH\"),\n    DueAt = DateTimeOffset.Parse(\"2026-11-01T00:00:00Z\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Dossier mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          },
          "400": {
            "description": "Un champ n'a pas passé la validation. Les clés du corps correspondent aux noms des champs. `team` est refusé lorsqu'il ne s'agit pas d'une équipe de révision active de cette application.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Team not active in this application": {
                    "value": {
                      "team": [
                        "Choose an active team of this application."
                      ]
                    }
                  },
                  "Invalid priority": {
                    "value": {
                      "priority": [
                        "\"URGENT\" is not a valid choice."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé API appartient à une autre application, ou il s'agit d'une clé avec un accès restreint : les endpoints Cases nécessitent une clé avec accès complet. Un token de membre de la console nécessite `write:cases`.",
            "content": {
              "application/json": {
                "examples": {
                  "Restricted API Key": {
                    "summary": "Clé API avec accès restreint",
                    "value": {
                      "detail": "This API key has no access to this endpoint."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "Membre de la Console sans write:cases, ou clé d'une autre application",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Dossier introuvable dans cette application.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No Case matches the given query."
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Supprimer le dossier",
        "description": "Supprimer définitivement un dossier. Ses brouillons de rapports réglementaires sont supprimés avec lui. Les vérifications, personnes, entreprises et transactions liées ne sont pas supprimées. Il n'existe aucun endpoint de restauration.\n\nSi le dossier comporte un rapport réglementaire finalisé, l'ensemble de la requête est refusé avec `409` et rien n'est supprimé. Le corps utilise `code: in_filed_report` et nomme chaque rapport avec `uuid`, `report_number`, `report_type` et `case_uuid`. Supprimez les rapports, puis réessayez la requête.",
        "operationId": "delete_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "delete",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.cases.delete(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.cases.delete(\"c1a5e000-0000-4000-8000-000000000001\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nif err := client.Cases.Delete(ctx, \"c1a5e000-0000-4000-8000-000000000001\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.cases().delete(\"c1a5e000-0000-4000-8000-000000000001\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->cases->delete('c1a5e000-0000-4000-8000-000000000001');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.delete(\"c1a5e000-0000-4000-8000-000000000001\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.Cases.DeleteAsync(\"c1a5e000-0000-4000-8000-000000000001\");"
          }
        ],
        "responses": {
          "204": {
            "description": "Dossier supprimé."
          },
          "403": {
            "description": "La clé ne peut pas supprimer de dossiers. Elle nécessite une clé à accès complet avec `write:cases`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Le dossier n'existe pas dans cette application ou a déjà été supprimé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Le dossier dispose d'un rapport réglementaire finalisé. Rien n'est supprimé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InFiledReportError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/assign/": {
      "post": {
        "summary": "Attribuer ou désattribuer un dossier",
        "description": "Attribuez le dossier à un utilisateur, ou désattribuez-le en envoyant assignee_user_id: null. assignee_email/assignee_name créent automatiquement une ligne User lorsque l'assigné n'existe pas encore.",
        "operationId": "assign_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "assign",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "assignee_user_id"
                ],
                "properties": {
                  "assignee_user_id": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "null pour désassigner."
                  },
                  "assignee_email": {
                    "type": "string",
                    "format": "email",
                    "nullable": true
                  },
                  "assignee_name": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "example": {
                "assignee_user_id": "9a000000-0000-4000-8000-0000000000aa"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/assign/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"assignee_user_id\": \"9a000000-0000-4000-8000-0000000000aa\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.assign(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    assignee_user_id=\"9a000000-0000-4000-8000-0000000000aa\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.assign(\"c1a5e000-0000-4000-8000-000000000001\", {\n  assignee_user_id: \"9a000000-0000-4000-8000-0000000000aa\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Assign(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesAssignParams{\n\tAssigneeUserID: didit.String(\"9a000000-0000-4000-8000-0000000000aa\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesAssignParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().assign(\"c1a5e000-0000-4000-8000-000000000001\", CasesAssignParams.builder()\n        .assigneeUserId(\"9a000000-0000-4000-8000-0000000000aa\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->assign('c1a5e000-0000-4000-8000-000000000001', [\n    'assignee_user_id' => '9a000000-0000-4000-8000-0000000000aa',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.assign(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  assignee_user_id: \"9a000000-0000-4000-8000-0000000000aa\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.AssignAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesAssignParams\n{\n    AssigneeUserId = \"9a000000-0000-4000-8000-0000000000aa\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Dossier assigné/non assigné.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/resolve/": {
      "post": {
        "summary": "Résoudre le dossier",
        "description": "Résolvez le dossier avec l'une des cinq résolutions : FALSE_POSITIVE (aucune préoccupation trouvée), VALID_THREAT (préoccupation confirmée), INCONCLUSIVE, REQUIREMENTS_NOT_MET ou REQUIREMENTS_SATISFIED. Bloqué avec 400 si la checklist du modèle n'est pas optionnelle et que des éléments restent incomplets, ou si le modèle exige une note de résolution et qu'aucune n'est fournie. Lorsque le modèle du dossier comporte une étape de contrôle à quatre yeux (four_eyes_checker_blueprint), la résolution est mise en attente (case.pending_resolution) et le dossier passe au modèle de vérificateur au lieu d'être résolu immédiatement ; un responsable différent doit appeler approve ou reject-approval. Soumettez une résolution à quatre yeux en tant que membre de la console : une résolution soumise par une clé API n'a pas d'auteur enregistré, donc approve et reject-approval renvoient 403 pour chaque appelant. Sur un modèle à quatre yeux, vous pouvez désigner le membre qui doit approuver avec `checker` : alors seul ce membre peut approuver ou rejeter la résolution, et le `checker` de la réponse le désigne. Sans `checker`, la résolution attend dans la file d'attente du modèle de vérificateur. L'envoi de `checker` pour un modèle sans étape de vérificateur renvoie 400.",
        "operationId": "resolve_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "resolve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "resolution"
                ],
                "properties": {
                  "resolution": {
                    "type": "string",
                    "enum": [
                      "FALSE_POSITIVE",
                      "VALID_THREAT",
                      "INCONCLUSIVE",
                      "REQUIREMENTS_NOT_MET",
                      "REQUIREMENTS_SATISFIED"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "nullable": true,
                    "description": "Requis lorsque le blueprint définit require_resolution_note."
                  },
                  "checker": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "Modèles à double contrôle uniquement. L'UUID utilisateur du membre qui doit approuver cette résolution (le même identifiant que `assigned_to.uuid` sur un dossier, ou `members[].user_id` sur une équipe de révision). Le membre doit avoir accès aux dossiers de cette application et ne peut pas être l'agent qui soumet la résolution. Omettez-le ou envoyez null pour laisser la résolution à la file d'attente du vérificateur."
                  }
                }
              },
              "examples": {
                "Resolve": {
                  "value": {
                    "resolution": "FALSE_POSITIVE",
                    "note": "Confirmed legitimate activity after reviewing documents."
                  }
                },
                "Four-eyes blueprint with a named checker": {
                  "value": {
                    "resolution": "VALID_THREAT",
                    "note": "Document tampering confirmed.",
                    "checker": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/resolve/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"resolution\": \"FALSE_POSITIVE\", \"note\": \"Confirmed legitimate activity after reviewing documents.\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.resolve(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    resolution=\"FALSE_POSITIVE\",\n    note=\"Confirmed legitimate activity after reviewing documents.\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.resolve(\"c1a5e000-0000-4000-8000-000000000001\", {\n  resolution: \"FALSE_POSITIVE\",\n  note: \"Confirmed legitimate activity after reviewing documents.\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Resolve(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesResolveParams{\n\tResolution: \"FALSE_POSITIVE\",\n\tNote:       didit.String(\"Confirmed legitimate activity after reviewing documents.\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesResolveParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().resolve(\"c1a5e000-0000-4000-8000-000000000001\", CasesResolveParams.builder()\n        .resolution(CasesResolveParams.Resolution.of(\"FALSE_POSITIVE\"))\n        .note(\"Confirmed legitimate activity after reviewing documents.\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->resolve('c1a5e000-0000-4000-8000-000000000001', [\n    'resolution' => 'FALSE_POSITIVE',\n    'note' => 'Confirmed legitimate activity after reviewing documents.',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.resolve(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  resolution: \"FALSE_POSITIVE\",\n  note: \"Confirmed legitimate activity after reviewing documents.\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.ResolveAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesResolveParams\n{\n    Resolution = \"FALSE_POSITIVE\",\n    Note = \"Confirmed legitimate activity after reviewing documents.\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Résolu, ou mis en attente pour approbation à 4 yeux.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          },
          "400": {
            "description": "La résolution a été refusée. Les erreurs non liées à un champ spécifique se présentent sous forme d'une liste de chaînes : une checklist incomplète, une note obligatoire manquante, ou un `checker` qui n'a pas pu être vérifié ou qui n'est pas un réviseur actif ayant accès au dossier pour cette application. Les erreurs de `checker` sont indexées par champ : le membre nommé est le responsable qui soumet la résolution, ou le modèle du dossier ne comporte pas d'étape de vérification.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    {
                      "type": "object",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "Incomplete checklist": {
                    "value": [
                      "Case has incomplete checklist items: Verify source of funds"
                    ]
                  },
                  "Resolution note required": {
                    "value": [
                      "A resolution note is required to resolve this case."
                    ]
                  },
                  "Reviewer access could not be verified": {
                    "value": [
                      "Reviewer access could not be verified. Try again."
                    ]
                  },
                  "Checker is not an active reviewer": {
                    "value": [
                      "Choose an active reviewer with case access to this application."
                    ]
                  },
                  "Checker is the submitting officer": {
                    "value": {
                      "checker": [
                        "The officer who submitted the resolution cannot be its checker."
                      ]
                    }
                  },
                  "Policy has no checker step": {
                    "value": {
                      "checker": [
                        "This review policy has no checker step, so the case resolves directly."
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/reopen/": {
      "post": {
        "summary": "Rouvrir le dossier",
        "description": "Repasse un dossier en attente de l'utilisateur ou résolu à l'état ouvert, en effaçant resolution, resolution_notes, resolved_at et resolved_by_email.",
        "operationId": "reopen_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "reopen",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/reopen/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.reopen(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.reopen(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Reopen(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().reopen(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->reopen('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.reopen(\"c1a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.ReopenAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Rouvrir le dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/request-info/": {
      "post": {
        "summary": "Demander des informations (en attente de l'utilisateur)",
        "description": "Passe un dossier ouvert à awaiting_user pendant que des informations supplémentaires sont collectées auprès de l'utilisateur vérifié. Échoue avec 400 si une résolution est actuellement en attente d'approbation à 4 yeux.",
        "operationId": "request_case_info",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "request_info",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/request-info/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.request_info(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.requestInfo(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RequestInfo(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().requestInfo(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->requestInfo('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.request_info(\"c1a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RequestInfoAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Demander des informations (en attente de l'utilisateur).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/escalate/": {
      "post": {
        "summary": "Faire remonter le dossier",
        "description": "Déplace le dossier vers l'escalation_blueprint configuré de son blueprint. Nécessite que le blueprint actuel ait escalation_enabled activé et un escalation_blueprint défini, sinon renvoie 400.",
        "operationId": "escalate_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "escalate",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/escalate/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.escalate(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.escalate(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Escalate(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().escalate(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->escalate('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.escalate(\"c1a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.EscalateAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Faire remonter le dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/transfer/": {
      "post": {
        "summary": "Transférer le dossier",
        "description": "Déplace le dossier vers un blueprint actif différent de la même application. Nécessite que le blueprint actuel ait transfer_enabled activé, sinon renvoie 400.",
        "operationId": "transfer_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "transfer",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target_blueprint"
                ],
                "properties": {
                  "target_blueprint": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              },
              "example": {
                "target_blueprint": "b1de0000-0000-4000-8000-000000000002"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/transfer/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"target_blueprint\": \"b1de0000-0000-4000-8000-000000000002\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.transfer(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    target_blueprint=\"b1de0000-0000-4000-8000-000000000002\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.transfer(\"c1a5e000-0000-4000-8000-000000000001\", {\n  target_blueprint: \"b1de0000-0000-4000-8000-000000000002\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Transfer(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesTransferParams{\n\tTargetBlueprint: \"b1de0000-0000-4000-8000-000000000002\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesTransferParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().transfer(\"c1a5e000-0000-4000-8000-000000000001\", CasesTransferParams.builder()\n        .targetBlueprint(\"b1de0000-0000-4000-8000-000000000002\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->transfer('c1a5e000-0000-4000-8000-000000000001', [\n    'target_blueprint' => 'b1de0000-0000-4000-8000-000000000002',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.transfer(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  target_blueprint: \"b1de0000-0000-4000-8000-000000000002\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.TransferAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesTransferParams\n{\n    TargetBlueprint = \"b1de0000-0000-4000-8000-000000000002\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Dossier transféré.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/approve/": {
      "post": {
        "summary": "Approuver la résolution échelonnée (principe des 4 yeux)",
        "description": "Applique une résolution préparée par resolve sur un modèle à quatre yeux. L'appelant doit être un responsable différent de celui qui l'a soumise, sinon une erreur 403 est renvoyée. Lorsque la résolution désigne un réviseur (le `checker` du dossier), seul ce membre peut l'approuver : tout autre appelant, y compris une clé API, reçoit une erreur 403.",
        "operationId": "approve_case_resolution",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "approve_resolution",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/approve/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.approve_resolution(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.approveResolution(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.ApproveResolution(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().approveResolution(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->approveResolution('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.approve_resolution(\"c1a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.ApproveResolutionAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Résolution appliquée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          },
          "409": {
            "description": "Le dossier n'a aucune résolution en attente d'approbation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'appelant ne peut pas approuver cette résolution : il l'a soumise, le dossier n'a pas de créateur enregistré, ou la résolution désigne un réviseur différent. Une clé API reçoit toujours cette erreur 403 lorsqu'un réviseur est désigné.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Caller submitted the resolution": {
                    "value": {
                      "detail": "The officer who submitted the resolution cannot approve it."
                    }
                  },
                  "No recorded maker": {
                    "value": {
                      "detail": "Case has no recorded maker for this pending resolution; approve is not permitted."
                    }
                  },
                  "Caller is not the named checker": {
                    "value": {
                      "detail": "Only the named checker can approve this resolution."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/reject-approval/": {
      "post": {
        "summary": "Rejeter la résolution préparée (principe des 4 yeux)",
        "description": "Rejeter une résolution préparée par resolve et renvoyer le dossier à son modèle de créateur. L'appelant doit être un responsable de la conformité différent de celui qui l'a soumise, sinon 403. Lorsque la résolution désigne un vérificateur (le `checker` du dossier), seul ce membre peut la rejeter : tout autre appelant, y compris une clé API, reçoit 403.",
        "operationId": "reject_case_resolution",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "reject_resolution",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "notes": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "example": {
                "notes": "Needs a clearer rationale before this can be approved."
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/reject-approval/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"notes\": \"Needs a clearer rationale before this can be approved.\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.reject_resolution(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    notes=\"Needs a clearer rationale before this can be approved.\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.rejectResolution(\"c1a5e000-0000-4000-8000-000000000001\", {\n  notes: \"Needs a clearer rationale before this can be approved.\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RejectResolution(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesRejectResolutionParams{\n\tNotes: didit.String(\"Needs a clearer rationale before this can be approved.\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesRejectResolutionParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().rejectResolution(\"c1a5e000-0000-4000-8000-000000000001\", CasesRejectResolutionParams.builder()\n        .notes(\"Needs a clearer rationale before this can be approved.\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->rejectResolution('c1a5e000-0000-4000-8000-000000000001', [\n    'notes' => 'Needs a clearer rationale before this can be approved.',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.reject_resolution(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  notes: \"Needs a clearer rationale before this can be approved.\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RejectResolutionAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesRejectResolutionParams\n{\n    Notes = \"Needs a clearer rationale before this can be approved.\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Résolution rejetée, dossier renvoyé au modèle de conception du créateur.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDetail"
                }
              }
            }
          },
          "409": {
            "description": "Le dossier n'a aucune résolution en attente d'approbation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'appelant ne peut pas rejeter cette résolution : il l'a soumise, le dossier n'a pas de créateur enregistré, ou la résolution désigne un réviseur différent. Une clé API reçoit toujours cette erreur 403 lorsqu'un réviseur est désigné.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Caller submitted the resolution": {
                    "value": {
                      "detail": "The officer who submitted the resolution cannot reject it."
                    }
                  },
                  "No recorded maker": {
                    "value": {
                      "detail": "Case has no recorded maker for this pending resolution; reject is not permitted."
                    }
                  },
                  "Caller is not the named checker": {
                    "value": {
                      "detail": "Only the named checker can reject this resolution."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/entity-actions/": {
      "post": {
        "operationId": "apply_case_entity_action",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "apply_entity_action",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CaseActionCaseEntityActionRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseActionCaseEntityActionRequest"
              },
              "example": {
                "client_reference": "e1a00000-0000-4000-8000-000000000001",
                "action": "add_tags",
                "tags": [
                  "source-of-funds-reviewed"
                ]
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CaseActionCaseEntityActionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseActionCaseEntityActionResult"
                }
              }
            },
            "description": ""
          },
          "409": {
            "description": "La référence appartient à un payload d'action différent."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Applique une action explicite au sujet du dossier. Fournissez un client_reference unique pour obtenir un accusé de réception d'action et rendre les tentatives idempotentes. La réutilisation de cette référence avec un payload différent renvoie une erreur 409. Avec une référence, examinez receipt.status même lorsque le statut HTTP est 200 : FAILED signifie qu'aucune action n'a été appliquée. Répéter une requête ayant échoué ne l'exécute pas à nouveau, sauf si retry est true. Omettre client_reference préserve la réponse héritée.",
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.apply_entity_action(\n    \"11111111-2222-3333-4444-555555555555\",\n    client_reference=\"e1a00000-0000-4000-8000-000000000001\",\n    action=\"add_tags\",\n    tags=[\"source-of-funds-reviewed\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.applyEntityAction(\"11111111-2222-3333-4444-555555555555\", {\n  client_reference: \"e1a00000-0000-4000-8000-000000000001\",\n  action: \"add_tags\",\n  tags: [\"source-of-funds-reviewed\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.ApplyEntityAction(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CaseActionCaseEntityActionRequest{\n\tClientReference: didit.String(\"e1a00000-0000-4000-8000-000000000001\"),\n\tAction:          didit.CaseActionActionEnum(\"add_tags\"),\n\tTags:            didit.Some([]string{\"source-of-funds-reviewed\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.CaseActionActionEnum;\nimport me.didit.types.CaseActionCaseEntityActionRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().applyEntityAction(\"11111111-2222-3333-4444-555555555555\", CaseActionCaseEntityActionRequest.builder()\n        .clientReference(\"e1a00000-0000-4000-8000-000000000001\")\n        .action(CaseActionActionEnum.of(\"add_tags\"))\n        .tags(List.of(\"source-of-funds-reviewed\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->applyEntityAction('11111111-2222-3333-4444-555555555555', [\n    'client_reference' => 'e1a00000-0000-4000-8000-000000000001',\n    'action' => 'add_tags',\n    'tags' => ['source-of-funds-reviewed'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.apply_entity_action(\n  \"11111111-2222-3333-4444-555555555555\",\n  client_reference: \"e1a00000-0000-4000-8000-000000000001\",\n  action: \"add_tags\",\n  tags: [\"source-of-funds-reviewed\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.ApplyEntityActionAsync(\"11111111-2222-3333-4444-555555555555\", new CaseActionCaseEntityActionRequest\n{\n    ClientReference = \"e1a00000-0000-4000-8000-000000000001\",\n    Action = \"add_tags\",\n    Tags = new string[] { \"source-of-funds-reviewed\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/print/": {
      "get": {
        "summary": "Imprimer le dossier (PDF)",
        "description": "Générer le dossier complet (résumé, sujet, état de la checklist, notes, sessions/transactions associées, événements, liste des rapports CRF) au format PDF et renvoyer une URL de téléchargement pré-signée.",
        "operationId": "print_case",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "print",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/print/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.print(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.print(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Print(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().print(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->print('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.print(\"c1a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.PrintAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "URL pré-signée du PDF.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/notes/": {
      "get": {
        "operationId": "list_case_notes",
        "x-didit-sdk": {
          "resource": "cases.notes",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Quel champ utiliser pour trier les résultats.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Nombre de résultats à retourner par page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "L'index initial à partir duquel renvoyer les résultats.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseCollaborationPaginatedCaseNoteList"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          },
          "404": {
            "description": "Le dossier ou la note n'est pas disponible pour cet appelant."
          }
        },
        "tags": [
          "Case Management"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.notes.list(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.notes.list(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.Notes.ListAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CasesNotesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().notes().list(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->notes->list('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.notes.list(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.Notes.ListAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "operationId": "create_case_note",
        "x-didit-sdk": {
          "resource": "cases.notes",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CaseCollaborationCaseNoteCreateRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseCollaborationCaseNoteCreateRequest"
              },
              "example": {
                "comment": "Proof of address matches the ID document."
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CaseCollaborationCaseNoteCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseCollaborationCaseNote"
                }
              }
            },
            "description": ""
          },
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseCollaborationCaseNote"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          },
          "404": {
            "description": "Le dossier ou la note n'est pas disponible pour cet appelant."
          },
          "409": {
            "description": "Cette référence client a déjà été utilisée pour une autre note ou pour une note qui a été supprimée."
          }
        },
        "tags": [
          "Case Management"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Ajouter une note associée au dossier. Une valeur facultative client_reference permet à une nouvelle tentative inchangée de renvoyer la même note sans doublon d'activité ni de notification. reply_to doit identifier une note active dans ce dossier. La réponse inclut un extrait délimité du parent sans copier cet extrait dans la réponse enregistrée.",
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.notes.create(\n    \"11111111-2222-3333-4444-555555555555\",\n    comment=\"Proof of address matches the ID document.\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.notes.create(\"11111111-2222-3333-4444-555555555555\", {\n  comment: \"Proof of address matches the ID document.\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Notes.Create(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CaseCollaborationCaseNoteCreateRequest{\n\tComment: \"Proof of address matches the ID document.\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CaseCollaborationCaseNoteCreateRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().notes().create(\"11111111-2222-3333-4444-555555555555\", CaseCollaborationCaseNoteCreateRequest.builder()\n        .comment(\"Proof of address matches the ID document.\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->notes->create('11111111-2222-3333-4444-555555555555', [\n    'comment' => 'Proof of address matches the ID document.',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.notes.create(\n  \"11111111-2222-3333-4444-555555555555\",\n  comment: \"Proof of address matches the ID document.\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Notes.CreateAsync(\"11111111-2222-3333-4444-555555555555\", new CaseCollaborationCaseNoteCreateRequest\n{\n    Comment = \"Proof of address matches the ID document.\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/notes/{note_uuid}/": {
      "patch": {
        "operationId": "root_partial_update",
        "x-didit-sdk": {
          "resource": "cases.notes",
          "method": "update",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "note_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CaseCollaborationPatchedCaseNoteUpdateRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseCollaborationPatchedCaseNoteUpdateRequest"
              },
              "example": {
                "is_pinned": true
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CaseCollaborationPatchedCaseNoteUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseCollaborationCaseNote"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          },
          "404": {
            "description": "Le dossier ou la note n'est pas disponible pour cet appelant."
          }
        },
        "tags": [
          "Case Management"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Épingler ou détacher une note existante. Les notes épinglées apparaissent en premier. Les modifications d'épinglage sont enregistrées dans l'activité du dossier et ne modifient ni les éléments de preuve ni les décisions sources.",
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.notes.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"11111111-2222-3333-4444-555555555555\",\n    is_pinned=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.notes.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n  {\n    is_pinned: true,\n  },\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Notes.Update(ctx, \"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\", didit.CaseCollaborationPatchedCaseNoteUpdateRequest{\n\tIsPinned: didit.Bool(true),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CaseCollaborationPatchedCaseNoteUpdateRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().notes().update(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\", CaseCollaborationPatchedCaseNoteUpdateRequest.builder()\n        .isPinned(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->notes->update('11111111-2222-3333-4444-555555555555', '11111111-2222-3333-4444-555555555555', [\n    'is_pinned' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.notes.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n  is_pinned: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Notes.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\", new CaseCollaborationPatchedCaseNoteUpdateRequest\n{\n    IsPinned = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "operationId": "delete_case_note",
        "x-didit-sdk": {
          "resource": "cases.notes",
          "method": "delete",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "note_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "La note est définitivement supprimée. Les réponses subsistent, sans l'extrait du parent supprimé. Les pièces jointes sont supprimées sauf si une autre note les utilise encore."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          },
          "404": {
            "description": "Le dossier ou la note n'est pas disponible pour cet appelant."
          }
        },
        "tags": [
          "Case Management"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.cases.notes.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.cases.notes.delete(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nif err := client.Cases.Notes.Delete(ctx, \"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.cases().notes().delete(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->cases->notes->delete('11111111-2222-3333-4444-555555555555', '11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.notes.delete(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\"\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.Cases.Notes.DeleteAsync(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/notes/presign/": {
      "post": {
        "summary": "Téléverser une pièce jointe à une note",
        "description": "Téléverser un fichier (JPEG, PNG, WebP, PDF, texte brut ou CSV ; 5 MB max) à joindre à une note. Renvoie le s3_key à transmettre dans le tableau attachments de la note.",
        "operationId": "upload_case_note_attachment",
        "x-didit-sdk": {
          "resource": "cases.notes",
          "method": "create_attachment_upload",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/notes/presign/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'file=@evidence.pdf'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.notes.create_attachment_upload(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    file=open(\"document.pdf\", \"rb\"),\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.notes.createAttachmentUpload(\"c1a5e000-0000-4000-8000-000000000001\", {\n  file: await fileFromPath(\"document.pdf\"),\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Notes.CreateAttachmentUpload(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesNotesCreateAttachmentUploadParams{\n\tFile: didit.FileFromPath(\"document.pdf\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\nimport me.didit.types.CasesNotesCreateAttachmentUploadParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().notes().createAttachmentUpload(\"c1a5e000-0000-4000-8000-000000000001\", CasesNotesCreateAttachmentUploadParams.builder()\n        .file(Path.of(\"document.pdf\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->notes->createAttachmentUpload('c1a5e000-0000-4000-8000-000000000001', [\n    'file' => File::fromPath('document.pdf'),\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.notes.create_attachment_upload(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  file: Pathname(\"document.pdf\")\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Notes.CreateAttachmentUploadAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesNotesCreateAttachmentUploadParams\n{\n    File = FileUpload.FromPath(\"document.pdf\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Fichier téléversé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "s3_key": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "file_size": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Aucun fichier, type de contenu non pris en charge, ou fichier supérieur à 5 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "get": {
        "summary": "Obtenir l'URL de pièce jointe d'une note",
        "description": "Générer une nouvelle URL de téléchargement pré-signée pour une pièce jointe déjà stockée dans l'une des notes du dossier.",
        "operationId": "get_case_note_attachment_url",
        "x-didit-sdk": {
          "resource": "cases.notes",
          "method": "retrieve_attachment_url",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          },
          {
            "name": "s3_key",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Le s3_key de la pièce jointe, tel que renvoyé par le téléversement ou listé sur la note.",
            "required": true
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/notes/presign/?s3_key=case-notes/c1a5e000-0000-4000-8000-000000000001/evidence.pdf' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.notes.retrieve_attachment_url(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    s3_key=\"your-s3-key\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.notes.retrieveAttachmentUrl(\"c1a5e000-0000-4000-8000-000000000001\", {\n  s3_key: \"your-s3-key\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Notes.RetrieveAttachmentURL(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesNotesRetrieveAttachmentURLParams{\n\tS3Key: \"your-s3-key\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesNotesRetrieveAttachmentUrlParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().notes().retrieveAttachmentUrl(\"c1a5e000-0000-4000-8000-000000000001\", CasesNotesRetrieveAttachmentUrlParams.builder()\n        .s3Key(\"your-s3-key\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->notes->retrieveAttachmentUrl('c1a5e000-0000-4000-8000-000000000001', [\n    's3_key' => 'your-s3-key',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.notes.retrieve_attachment_url(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  s3_key: \"your-s3-key\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Notes.RetrieveAttachmentUrlAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesNotesRetrieveAttachmentUrlParams\n{\n    S3Key = \"your-s3-key\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "URL pré-signée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "s3_key": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "filename": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "s3_key manquante ou n'appartenant pas à ce dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/links/": {
      "get": {
        "summary": "Lister les liens du dossier",
        "description": "Lister les sessions, sessions d'entreprise et transactions rattachées au dossier.",
        "operationId": "list_case_links",
        "x-didit-sdk": {
          "resource": "cases.links",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/links/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.links.list(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.links.list(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Links.List(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().links().list(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->links->list('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.links.list(\"c1a5e000-0000-4000-8000-000000000001\").each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Links.ListAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Liens du dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CaseLink"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Ajouter un lien vers un dossier",
        "description": "Associer une session, une session d'entreprise ou une transaction au dossier. Rejeté avec le code 400 si l'entité appartient à un sujet différent de celui du dossier.",
        "operationId": "create_case_link",
        "x-didit-sdk": {
          "resource": "cases.links",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "entity_type",
                  "entity_uuid"
                ],
                "properties": {
                  "entity_type": {
                    "type": "string",
                    "enum": [
                      "session",
                      "business_session",
                      "transaction"
                    ]
                  },
                  "entity_uuid": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              },
              "example": {
                "entity_type": "transaction",
                "entity_uuid": "77000000-0000-4000-8000-000000000077"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/links/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"entity_type\": \"transaction\", \"entity_uuid\": \"77000000-0000-4000-8000-000000000077\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.links.create(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    entity_type=\"transaction\",\n    entity_uuid=\"77000000-0000-4000-8000-000000000077\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.links.create(\"c1a5e000-0000-4000-8000-000000000001\", {\n  entity_type: \"transaction\",\n  entity_uuid: \"77000000-0000-4000-8000-000000000077\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Links.Create(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesLinksCreateParams{\n\tEntityType: \"transaction\",\n\tEntityUUID: \"77000000-0000-4000-8000-000000000077\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesLinksCreateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().links().create(\"c1a5e000-0000-4000-8000-000000000001\", CasesLinksCreateParams.builder()\n        .entityType(CasesLinksCreateParams.EntityType.of(\"transaction\"))\n        .entityUuid(\"77000000-0000-4000-8000-000000000077\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->links->create('c1a5e000-0000-4000-8000-000000000001', [\n    'entity_type' => 'transaction',\n    'entity_uuid' => '77000000-0000-4000-8000-000000000077',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.links.create(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  entity_type: \"transaction\",\n  entity_uuid: \"77000000-0000-4000-8000-000000000077\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Links.CreateAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesLinksCreateParams\n{\n    EntityType = \"transaction\",\n    EntityUuid = \"77000000-0000-4000-8000-000000000077\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Lien créé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseLink"
                }
              }
            }
          },
          "400": {
            "description": "L'entité appartient à un profil différent de celui du sujet du dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/links/{link_uuid}/": {
      "delete": {
        "summary": "Supprimer le lien du dossier",
        "description": "Détacher du dossier une session, une session d'entreprise ou une transaction liée.",
        "operationId": "delete_case_link",
        "x-didit-sdk": {
          "resource": "cases.links",
          "method": "delete",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          },
          {
            "name": "link_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11000000-0000-4000-8000-000000000004"
            },
            "description": "UUID du lien."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/links/11000000-0000-4000-8000-000000000004/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.cases.links.delete(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    \"11000000-0000-4000-8000-000000000004\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.cases.links.delete(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  \"11000000-0000-4000-8000-000000000004\",\n);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nif err := client.Cases.Links.Delete(ctx, \"c1a5e000-0000-4000-8000-000000000001\", \"11000000-0000-4000-8000-000000000004\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.cases().links().delete(\"c1a5e000-0000-4000-8000-000000000001\", \"11000000-0000-4000-8000-000000000004\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->cases->links->delete('c1a5e000-0000-4000-8000-000000000001', '11000000-0000-4000-8000-000000000004');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.links.delete(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  \"11000000-0000-4000-8000-000000000004\"\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.Cases.Links.DeleteAsync(\"c1a5e000-0000-4000-8000-000000000001\", \"11000000-0000-4000-8000-000000000004\");"
          }
        ],
        "responses": {
          "204": {
            "description": "Lien supprimé."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/events/": {
      "get": {
        "summary": "Lister les événements du dossier",
        "description": "Chronologie d'audit en lecture seule du dossier (création, changements de statut, attribution, résolution, escalade, transferts, modifications de tag/priorité/date d'échéance, actions sur l'entité, et plus encore).",
        "operationId": "list_case_events",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "list_events",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            },
            "description": "Taille de la page."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            },
            "description": "Décalage de départ (base zéro)."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/events/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.list_events(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.listEvents(\"c1a5e000-0000-4000-8000-000000000001\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.ListEventsAutoPaging(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesListEventsParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().listEvents(\"c1a5e000-0000-4000-8000-000000000001\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->listEvents('c1a5e000-0000-4000-8000-000000000001') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.list_events(\"c1a5e000-0000-4000-8000-000000000001\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.ListEventsAsync(\"c1a5e000-0000-4000-8000-000000000001\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Événements paginés, du plus récent au plus ancien.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de lignes correspondantes. Exact jusqu'à 100, plafonné à 100 au-delà pour des raisons de performance. Fiez-vous à la valeur null de `next` pour détecter la dernière page."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou null."
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou null."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaseEvent"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/checklist/": {
      "get": {
        "summary": "Lister la checklist du dossier",
        "description": "Lister les éléments de la liste de contrôle du dossier, copiés depuis content_config.checklist.items du modèle lors de la création, ordonnés.",
        "operationId": "list_case_checklist",
        "x-didit-sdk": {
          "resource": "cases.checklist",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/checklist/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.checklist.list(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.checklist.list(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Checklist.List(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().checklist().list(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->checklist->list('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.checklist.list(\"c1a5e000-0000-4000-8000-000000000001\").each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Checklist.ListAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Éléments de liste de contrôle.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CaseChecklistItem"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/checklist/{item_uuid}/": {
      "patch": {
        "summary": "Activer ou désactiver l'élément de la liste de contrôle",
        "description": "Marquer un élément de la checklist comme terminé ou incomplet. La résolution est bloquée tant qu'un élément est incomplet, à moins que le blueprint n'indique que la checklist est facultative.",
        "operationId": "toggle_case_checklist_item",
        "x-didit-sdk": {
          "resource": "cases.checklist",
          "method": "toggle_item",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          },
          {
            "name": "item_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c4ec0000-0000-4000-8000-000000000005"
            },
            "description": "UUID de l'élément de liste de contrôle."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "is_completed"
                ],
                "properties": {
                  "is_completed": {
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "is_completed": true
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/checklist/c4ec0000-0000-4000-8000-000000000005/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"is_completed\": true}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.checklist.toggle_item(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    \"c4ec0000-0000-4000-8000-000000000005\",\n    is_completed=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.checklist.toggleItem(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  \"c4ec0000-0000-4000-8000-000000000005\",\n  {\n    is_completed: true,\n  },\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Checklist.ToggleItem(ctx, \"c1a5e000-0000-4000-8000-000000000001\", \"c4ec0000-0000-4000-8000-000000000005\", didit.CasesChecklistToggleItemParams{\n\tIsCompleted: true,\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesChecklistToggleItemParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().checklist().toggleItem(\"c1a5e000-0000-4000-8000-000000000001\", \"c4ec0000-0000-4000-8000-000000000005\", CasesChecklistToggleItemParams.builder()\n        .isCompleted(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->checklist->toggleItem('c1a5e000-0000-4000-8000-000000000001', 'c4ec0000-0000-4000-8000-000000000005', [\n    'is_completed' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.checklist.toggle_item(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  \"c4ec0000-0000-4000-8000-000000000005\",\n  is_completed: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Checklist.ToggleItemAsync(\"c1a5e000-0000-4000-8000-000000000001\", \"c4ec0000-0000-4000-8000-000000000005\", new CasesChecklistToggleItemParams\n{\n    IsCompleted = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Élément de la liste de contrôle mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseChecklistItem"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/aml/": {
      "get": {
        "summary": "Lister les correspondances AML du dossier",
        "description": "Lister les correspondances de filtrage AML pour le sujet du dossier. Même structure que les résultats renvoyés par POST /v3/aml/.",
        "operationId": "list_case_aml_hits",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "list_aml_hits",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/aml/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.list_aml_hits(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.listAmlHits(\"c1a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.ListAMLHits(ctx, \"c1a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().listAmlHits(\"c1a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->listAmlHits('c1a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.list_aml_hits(\"c1a5e000-0000-4000-8000-000000000001\").each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.ListAmlHitsAsync(\"c1a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Correspondances AML.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AMLScreening"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/statistics/": {
      "get": {
        "summary": "Analytique des dossiers",
        "description": "Analyses agrégées des dossiers pour la plage de dates (par défaut les 30 derniers jours ; max 731 jours). Les graphiques, tableaux, totaux, événements d'attribution et effectifs actuels des files d'attente utilisent les mêmes filtres limités à l'application. Les filtres utilisent les valeurs actuelles des dossiers. Les dates s'appliquent à chaque événement de métrique, de sorte que les dossiers plus anciens attribués ou résolus au cours de la période restent inclus. La profondeur de la file d'attente est indépendante de la plage de dates. Des filtres non valides renvoient 400 ; un modèle ou une personne assignée inconnue renvoie un résultat vide.",
        "operationId": "get_case_analytics",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "retrieve_statistics",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "date_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Début de la plage (inclus). Valeur par défaut : il y a 30 jours."
          },
          {
            "name": "date_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Fin de la plage (incluse). Valeur par défaut : aujourd'hui."
          },
          {
            "name": "blueprint",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filtrer par l'UUID du blueprint actuel."
          },
          {
            "name": "assigned_to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filtrer par l'UUID de l'utilisateur réviseur actuellement assigné."
          },
          {
            "name": "priority",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "LOW",
                "MEDIUM",
                "HIGH"
              ]
            },
            "description": "Filtrer par priorité actuelle du dossier."
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "MANUAL",
                "AML_SCREENING",
                "TRANSACTION_RULE",
                "WORKFLOW_BUILDER"
              ]
            },
            "description": "Filtrer par source de création du dossier."
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "OPEN",
                "AWAITING_USER",
                "RESOLVED"
              ]
            },
            "description": "Filtrer par statut actuel du dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/statistics/?date_from=2026-06-01&date_to=2026-06-30' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.retrieve_statistics()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.retrieveStatistics();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RetrieveStatistics(ctx, didit.CasesRetrieveStatisticsParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().retrieveStatistics();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->retrieveStatistics();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.retrieve_statistics\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RetrieveStatisticsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Payload d'analyse.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "series": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string",
                            "format": "date"
                          },
                          "created": {
                            "type": "integer"
                          },
                          "reviewed": {
                            "type": "integer"
                          }
                        }
                      }
                    },
                    "tables": {
                      "type": "object",
                      "properties": {
                        "officer": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string",
                                "description": "Valeur de la dimension : e-mail du responsable, \"blueprint_name:uuid\", source ou statut. \"unassigned\"/\"none\" pour les dimensions manquantes."
                              },
                              "created": {
                                "type": "integer"
                              },
                              "assigned": {
                                "type": "integer"
                              },
                              "resolved": {
                                "type": "integer"
                              },
                              "threat_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "false_positive_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "unresolved": {
                                "type": "integer"
                              },
                              "reassignment_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "escalation_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_assign_hours": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_resolve_hours": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_handling_hours": {
                                "type": "number",
                                "format": "float"
                              }
                            }
                          }
                        },
                        "blueprint": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string",
                                "description": "Valeur de la dimension : e-mail du responsable, \"blueprint_name:uuid\", source ou statut. \"unassigned\"/\"none\" pour les dimensions manquantes."
                              },
                              "created": {
                                "type": "integer"
                              },
                              "assigned": {
                                "type": "integer"
                              },
                              "resolved": {
                                "type": "integer"
                              },
                              "threat_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "false_positive_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "unresolved": {
                                "type": "integer"
                              },
                              "reassignment_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "escalation_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_assign_hours": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_resolve_hours": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_handling_hours": {
                                "type": "number",
                                "format": "float"
                              }
                            }
                          }
                        },
                        "source": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string",
                                "description": "Valeur de la dimension : e-mail du responsable, \"blueprint_name:uuid\", source ou statut. \"unassigned\"/\"none\" pour les dimensions manquantes."
                              },
                              "created": {
                                "type": "integer"
                              },
                              "assigned": {
                                "type": "integer"
                              },
                              "resolved": {
                                "type": "integer"
                              },
                              "threat_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "false_positive_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "unresolved": {
                                "type": "integer"
                              },
                              "reassignment_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "escalation_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_assign_hours": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_resolve_hours": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_handling_hours": {
                                "type": "number",
                                "format": "float"
                              }
                            }
                          }
                        },
                        "status": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string",
                                "description": "Valeur de la dimension : e-mail du responsable, \"blueprint_name:uuid\", source ou statut. \"unassigned\"/\"none\" pour les dimensions manquantes."
                              },
                              "created": {
                                "type": "integer"
                              },
                              "assigned": {
                                "type": "integer"
                              },
                              "resolved": {
                                "type": "integer"
                              },
                              "threat_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "false_positive_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "unresolved": {
                                "type": "integer"
                              },
                              "reassignment_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "escalation_rate": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_assign_hours": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_resolve_hours": {
                                "type": "number",
                                "format": "float"
                              },
                              "avg_handling_hours": {
                                "type": "number",
                                "format": "float"
                              }
                            }
                          }
                        }
                      }
                    },
                    "totals": {
                      "type": "object",
                      "properties": {
                        "created": {
                          "type": "integer"
                        },
                        "assigned": {
                          "type": "integer"
                        },
                        "resolved": {
                          "type": "integer"
                        },
                        "threat_rate": {
                          "type": "number",
                          "format": "float"
                        },
                        "false_positive_rate": {
                          "type": "number",
                          "format": "float"
                        },
                        "unresolved": {
                          "type": "integer"
                        },
                        "reassignment_rate": {
                          "type": "number",
                          "format": "float"
                        },
                        "escalation_rate": {
                          "type": "number",
                          "format": "float"
                        },
                        "avg_assign_hours": {
                          "type": "number",
                          "format": "float"
                        },
                        "avg_resolve_hours": {
                          "type": "number",
                          "format": "float"
                        },
                        "avg_handling_hours": {
                          "type": "number",
                          "format": "float"
                        }
                      }
                    },
                    "queue": {
                      "type": "object",
                      "description": "Instantané en direct, non limité à la plage de dates.",
                      "properties": {
                        "open": {
                          "type": "integer"
                        },
                        "overdue": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/bulk/status/": {
      "post": {
        "summary": "Mettre à jour en masse le statut des dossiers",
        "description": "Appliquez la même transition de statut à plusieurs dossiers en un seul appel : OPEN rouvre, AWAITING_USER demande des informations, RESOLVED résout (résolution requise). Chaque dossier est évalué indépendamment ; les échecs de critères de passage (checklist incomplète, note requise manquante) sont signalés par dossier sans interrompre le lot.",
        "operationId": "bulk_update_case_status",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "bulk_update_status",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "case_uuids",
                  "status"
                ],
                "properties": {
                  "case_uuids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "OPEN",
                      "AWAITING_USER",
                      "RESOLVED"
                    ]
                  },
                  "resolution": {
                    "type": "string",
                    "enum": [
                      "FALSE_POSITIVE",
                      "VALID_THREAT",
                      "INCONCLUSIVE",
                      "REQUIREMENTS_NOT_MET",
                      "REQUIREMENTS_SATISFIED"
                    ],
                    "description": "Requis lorsque le statut est RESOLVED."
                  },
                  "note": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "example": {
                "case_uuids": [
                  "c1a5e000-0000-4000-8000-000000000001"
                ],
                "status": "RESOLVED",
                "resolution": "FALSE_POSITIVE"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/bulk/status/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"case_uuids\": [\"c1a5e000-0000-4000-8000-000000000001\"], \"status\": \"RESOLVED\", \"resolution\": \"FALSE_POSITIVE\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.bulk_update_status(\n    case_uuids=[\"c1a5e000-0000-4000-8000-000000000001\"],\n    status=\"RESOLVED\",\n    resolution=\"FALSE_POSITIVE\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.bulkUpdateStatus({\n  case_uuids: [\"c1a5e000-0000-4000-8000-000000000001\"],\n  status: \"RESOLVED\",\n  resolution: \"FALSE_POSITIVE\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.BulkUpdateStatus(ctx, didit.CasesBulkUpdateStatusParams{\n\tCaseUUIDs:  []string{\"c1a5e000-0000-4000-8000-000000000001\"},\n\tStatus:     \"RESOLVED\",\n\tResolution: didit.Some(didit.CasesBulkUpdateStatusParamsResolution(\"FALSE_POSITIVE\")),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.CasesBulkUpdateStatusParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().bulkUpdateStatus(CasesBulkUpdateStatusParams.builder()\n        .caseUuids(List.of(\"c1a5e000-0000-4000-8000-000000000001\"))\n        .status(CasesBulkUpdateStatusParams.Status.of(\"RESOLVED\"))\n        .resolution(CasesBulkUpdateStatusParams.Resolution.of(\"FALSE_POSITIVE\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->bulkUpdateStatus([\n    'case_uuids' => ['c1a5e000-0000-4000-8000-000000000001'],\n    'status' => 'RESOLVED',\n    'resolution' => 'FALSE_POSITIVE',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.bulk_update_status(\n  case_uuids: [\"c1a5e000-0000-4000-8000-000000000001\"],\n  status: \"RESOLVED\",\n  resolution: \"FALSE_POSITIVE\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.BulkUpdateStatusAsync(new CasesBulkUpdateStatusParams\n{\n    CaseUuids = new string[] { \"c1a5e000-0000-4000-8000-000000000001\" },\n    Status = \"RESOLVED\",\n    Resolution = new CasesBulkUpdateStatusParamsResolution(\"FALSE_POSITIVE\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Résultats par dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseBulkUpdateResult"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/bulk/assign/": {
      "post": {
        "summary": "Assigner des dossiers en masse",
        "description": "Attribuez (ou désattribuez, avec assignee_user_id: null) plusieurs dossiers à la fois. Tous les dossiers doivent partager le même blueprint ; les non-concordances sont signalées par dossier sans interrompre le lot.",
        "operationId": "bulk_assign_cases",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "bulk_assign",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Cases"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "case_uuids",
                  "assignee_user_id"
                ],
                "properties": {
                  "case_uuids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1
                  },
                  "assignee_user_id": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  },
                  "assignee_email": {
                    "type": "string",
                    "format": "email",
                    "nullable": true
                  },
                  "assignee_name": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "example": {
                "case_uuids": [
                  "c1a5e000-0000-4000-8000-000000000001"
                ],
                "assignee_user_id": "9a000000-0000-4000-8000-0000000000aa"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/bulk/assign/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"case_uuids\": [\"c1a5e000-0000-4000-8000-000000000001\"], \"assignee_user_id\": \"9a000000-0000-4000-8000-0000000000aa\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.bulk_assign(\n    case_uuids=[\"c1a5e000-0000-4000-8000-000000000001\"],\n    assignee_user_id=\"9a000000-0000-4000-8000-0000000000aa\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.bulkAssign({\n  case_uuids: [\"c1a5e000-0000-4000-8000-000000000001\"],\n  assignee_user_id: \"9a000000-0000-4000-8000-0000000000aa\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.BulkAssign(ctx, didit.CasesBulkAssignParams{\n\tCaseUUIDs:      []string{\"c1a5e000-0000-4000-8000-000000000001\"},\n\tAssigneeUserID: didit.String(\"9a000000-0000-4000-8000-0000000000aa\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.CasesBulkAssignParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().bulkAssign(CasesBulkAssignParams.builder()\n        .caseUuids(List.of(\"c1a5e000-0000-4000-8000-000000000001\"))\n        .assigneeUserId(\"9a000000-0000-4000-8000-0000000000aa\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->bulkAssign([\n    'case_uuids' => ['c1a5e000-0000-4000-8000-000000000001'],\n    'assignee_user_id' => '9a000000-0000-4000-8000-0000000000aa',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.bulk_assign(\n  case_uuids: [\"c1a5e000-0000-4000-8000-000000000001\"],\n  assignee_user_id: \"9a000000-0000-4000-8000-0000000000aa\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.BulkAssignAsync(new CasesBulkAssignParams\n{\n    CaseUuids = new string[] { \"c1a5e000-0000-4000-8000-000000000001\" },\n    AssigneeUserId = \"9a000000-0000-4000-8000-0000000000aa\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Résultats par dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseBulkUpdateResult"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/blueprints/": {
      "get": {
        "summary": "Lister les blueprints",
        "description": "Lister les blueprints de dossier pour l'application.",
        "operationId": "list_case_blueprints",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Blueprints"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            },
            "description": "Taille de la page."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            },
            "description": "Décalage de départ (base zéro)."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/blueprints/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.blueprints.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.blueprints.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.Blueprints.ListAutoPaging(ctx, didit.CasesBlueprintsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().blueprints().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->blueprints->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.blueprints.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.Blueprints.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginée des plans types.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de lignes correspondantes, plafonné à 100 pour des raisons de performance."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaseBlueprintListItem"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer un blueprint",
        "description": "Créez un blueprint de dossier : paramètres généraux (attribution, escalade, transfert, contrôle à quatre yeux) ainsi que content_config, les six sections qui structurent la page du dossier. Définissez publish=false pour créer un brouillon non publié ; la publication crée sa première version active. L'abandon d'un brouillon jamais publié le supprime.",
        "operationId": "create_case_blueprint",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Blueprints"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "assignee_pool"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 24,
                    "description": "24 caractères au maximum, ex. « investigation AML »."
                  },
                  "description": {
                    "type": "string",
                    "nullable": true
                  },
                  "assignee_pool": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1,
                    "description": "Liste des UUID d'utilisateurs. Les tableaux vides sont rejetés avec « Pick at least one assignee »."
                  },
                  "assignment_method": {
                    "type": "string",
                    "enum": [
                      "MANUAL",
                      "AUTOMATIC"
                    ],
                    "default": "MANUAL"
                  },
                  "max_active_cases": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "description": "Seuil du mode automatique : « moins de N dossiers de ce modèle attribués »."
                  },
                  "escalation_enabled": {
                    "type": "boolean",
                    "default": false
                  },
                  "escalation_blueprint": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "UUID du blueprint cible. Non imposé au moment de l'enregistrement, mais l'action d'escalade échoue avec un code 400 tant que escalation_enabled et escalation_blueprint ne sont pas tous deux définis."
                  },
                  "transfer_enabled": {
                    "type": "boolean",
                    "default": false
                  },
                  "four_eyes_checker_blueprint": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "Activer ce paramètre active la revue à quatre yeux : les résolutions sur ce modèle sont placées dans la file d'attente du modèle de contrôle."
                  },
                  "require_resolution_note": {
                    "type": "boolean",
                    "default": false
                  },
                  "content_config": {
                    "$ref": "#/components/schemas/CaseContentConfig"
                  },
                  "is_active": {
                    "type": "boolean",
                    "default": true
                  },
                  "default_deadline_hours": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "maximum": 8760,
                    "description": "Délai par défaut pour les dossiers nouvellement ouverts. Les délais des dossiers existants restent inchangés."
                  },
                  "publish": {
                    "type": "boolean",
                    "writeOnly": true,
                    "default": true,
                    "description": "Définissez sur false pour enregistrer un brouillon jamais publié. L'enregistrement reste inactif à la version 0 jusqu'à ce que le brouillon soit explicitement publié. L'omission de ce champ préserve la création immédiate pour les intégrations existantes."
                  }
                }
              },
              "example": {
                "name": "AML investigation",
                "assignee_pool": [
                  "9a000000-0000-4000-8000-0000000000aa"
                ],
                "assignment_method": "AUTOMATIC",
                "max_active_cases": 15,
                "require_resolution_note": true,
                "content_config": {
                  "aml_control": {
                    "enabled": true,
                    "financial": true,
                    "identity": false
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/blueprints/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"name\": \"AML investigation\", \"assignee_pool\": [\"9a000000-0000-4000-8000-0000000000aa\"], \"assignment_method\": \"AUTOMATIC\", \"max_active_cases\": 15, \"require_resolution_note\": true, \"content_config\": {\"aml_control\": {\"enabled\": true, \"financial\": true, \"identity\": false}}}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.blueprints.create(\n    name=\"AML investigation\",\n    assignee_pool=[\"9a000000-0000-4000-8000-0000000000aa\"],\n    assignment_method=\"AUTOMATIC\",\n    max_active_cases=15,\n    require_resolution_note=True,\n    content_config={\n        \"aml_control\": {\n            \"enabled\": True,\n            \"financial\": True,\n            \"identity\": False,\n        },\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.blueprints.create({\n  name: \"AML investigation\",\n  assignee_pool: [\"9a000000-0000-4000-8000-0000000000aa\"],\n  assignment_method: \"AUTOMATIC\",\n  max_active_cases: 15,\n  require_resolution_note: true,\n  content_config: {\n    aml_control: {\n      enabled: true,\n      financial: true,\n      identity: false,\n    },\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Blueprints.Create(ctx, didit.CasesBlueprintsCreateParams{\n\tName:                  \"AML investigation\",\n\tAssigneePool:          []string{\"9a000000-0000-4000-8000-0000000000aa\"},\n\tAssignmentMethod:      didit.Some(didit.CasesBlueprintsCreateParamsAssignmentMethod(\"AUTOMATIC\")),\n\tMaxActiveCases:        didit.Int(15),\n\tRequireResolutionNote: didit.Bool(true),\n\tContentConfig: didit.Some(didit.CaseContentConfigParam{\n\t\tAMLControl: didit.Some(didit.CaseContentConfigParamAMLControl{\n\t\t\tEnabled:   didit.Bool(true),\n\t\t\tFinancial: didit.Bool(true),\n\t\t\tIdentity:  didit.Bool(false),\n\t\t}),\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.CaseContentConfig;\nimport me.didit.types.CasesBlueprintsCreateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().blueprints().create(CasesBlueprintsCreateParams.builder()\n        .name(\"AML investigation\")\n        .assigneePool(List.of(\"9a000000-0000-4000-8000-0000000000aa\"))\n        .assignmentMethod(CasesBlueprintsCreateParams.AssignmentMethod.of(\"AUTOMATIC\"))\n        .maxActiveCases(15L)\n        .requireResolutionNote(true)\n        .contentConfig(CaseContentConfig.builder()\n                .amlControl(CaseContentConfig.AmlControl.builder()\n                        .enabled(true)\n                        .financial(true)\n                        .identity(false)\n                        .build())\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->blueprints->create([\n    'name' => 'AML investigation',\n    'assignee_pool' => ['9a000000-0000-4000-8000-0000000000aa'],\n    'assignment_method' => 'AUTOMATIC',\n    'max_active_cases' => 15,\n    'require_resolution_note' => true,\n    'content_config' => [\n        'aml_control' => [\n            'enabled' => true,\n            'financial' => true,\n            'identity' => false,\n        ],\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.blueprints.create(\n  name: \"AML investigation\",\n  assignee_pool: [\"9a000000-0000-4000-8000-0000000000aa\"],\n  assignment_method: \"AUTOMATIC\",\n  max_active_cases: 15,\n  require_resolution_note: true,\n  content_config: {\n    aml_control: {\n      enabled: true,\n      financial: true,\n      identity: false,\n    },\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Blueprints.CreateAsync(new CasesBlueprintsCreateParams\n{\n    Name = \"AML investigation\",\n    AssigneePool = new string[] { \"9a000000-0000-4000-8000-0000000000aa\" },\n    AssignmentMethod = new CasesBlueprintsCreateParamsAssignmentMethod(\"AUTOMATIC\"),\n    MaxActiveCases = 15,\n    RequireResolutionNote = true,\n    ContentConfig = new CaseContentConfig\n    {\n        AmlControl = new CaseContentConfigAmlControl\n        {\n            Enabled = true,\n            Financial = true,\n            Identity = false,\n        },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Blueprint créé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseBlueprintDetail"
                }
              }
            }
          },
          "400": {
            "description": "Nom de plus de 24 caractères, assignee_pool vide, ou blueprint référencé (escalation/checker) introuvable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/blueprints/{blueprint_uuid}/": {
      "get": {
        "summary": "Obtenir le blueprint",
        "description": "Récupérer un modèle, y compris ses sources de création connectées (configuration AML, règles de transaction, nœuds de workflow) et les modèles qui effectuent une escalade vers lui.",
        "operationId": "get_case_blueprint",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "retrieve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Blueprints"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "blueprint_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "b1de0000-0000-4000-8000-000000000002"
            },
            "description": "UUID du blueprint."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/blueprints/b1de0000-0000-4000-8000-000000000002/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.blueprints.retrieve(\n    \"b1de0000-0000-4000-8000-000000000002\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.blueprints.retrieve(\"b1de0000-0000-4000-8000-000000000002\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Blueprints.Retrieve(ctx, \"b1de0000-0000-4000-8000-000000000002\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().blueprints().retrieve(\"b1de0000-0000-4000-8000-000000000002\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->blueprints->retrieve('b1de0000-0000-4000-8000-000000000002');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.blueprints.retrieve(\"b1de0000-0000-4000-8000-000000000002\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Blueprints.RetrieveAsync(\"b1de0000-0000-4000-8000-000000000002\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détail du blueprint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseBlueprintDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour le blueprint",
        "description": "Mettre à jour partiellement les paramètres généraux ou content_config d'un blueprint.",
        "operationId": "update_case_blueprint",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "update",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Blueprints"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "blueprint_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "b1de0000-0000-4000-8000-000000000002"
            },
            "description": "UUID du blueprint."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 24,
                    "description": "24 caractères au maximum, ex. « investigation AML »."
                  },
                  "description": {
                    "type": "string",
                    "nullable": true
                  },
                  "assignee_pool": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1,
                    "description": "Liste des UUID d'utilisateurs. Les tableaux vides sont rejetés avec « Pick at least one assignee »."
                  },
                  "assignment_method": {
                    "type": "string",
                    "enum": [
                      "MANUAL",
                      "AUTOMATIC"
                    ]
                  },
                  "max_active_cases": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "description": "Seuil du mode automatique : « moins de N dossiers de ce modèle attribués »."
                  },
                  "escalation_enabled": {
                    "type": "boolean"
                  },
                  "escalation_blueprint": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "UUID du blueprint cible. Non imposé au moment de l'enregistrement, mais l'action d'escalade échoue avec un code 400 tant que escalation_enabled et escalation_blueprint ne sont pas tous deux définis."
                  },
                  "transfer_enabled": {
                    "type": "boolean"
                  },
                  "four_eyes_checker_blueprint": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "Activer ce paramètre active la revue à quatre yeux : les résolutions sur ce modèle sont placées dans la file d'attente du modèle de contrôle."
                  },
                  "require_resolution_note": {
                    "type": "boolean"
                  },
                  "content_config": {
                    "$ref": "#/components/schemas/CaseContentConfig"
                  },
                  "is_active": {
                    "type": "boolean"
                  },
                  "default_deadline_hours": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "maximum": 8760,
                    "description": "Délai par défaut pour les dossiers nouvellement ouverts. Les délais des dossiers existants restent inchangés."
                  },
                  "expected_version": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "La version ouverte par l'éditeur. Une version obsolète renvoie 409 sans modifier la politique d'examen."
                  }
                }
              },
              "example": {
                "transfer_enabled": true
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/blueprints/b1de0000-0000-4000-8000-000000000002/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"transfer_enabled\": true}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.blueprints.update(\n    \"b1de0000-0000-4000-8000-000000000002\",\n    transfer_enabled=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.blueprints.update(\"b1de0000-0000-4000-8000-000000000002\", {\n  transfer_enabled: true,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Blueprints.Update(ctx, \"b1de0000-0000-4000-8000-000000000002\", didit.CasesBlueprintsUpdateParams{\n\tTransferEnabled: didit.Bool(true),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesBlueprintsUpdateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().blueprints().update(\"b1de0000-0000-4000-8000-000000000002\", CasesBlueprintsUpdateParams.builder()\n        .transferEnabled(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->blueprints->update('b1de0000-0000-4000-8000-000000000002', [\n    'transfer_enabled' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.blueprints.update(\n  \"b1de0000-0000-4000-8000-000000000002\",\n  transfer_enabled: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Blueprints.UpdateAsync(\"b1de0000-0000-4000-8000-000000000002\", new CasesBlueprintsUpdateParams\n{\n    TransferEnabled = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Blueprint mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseBlueprintDetail"
                }
              }
            }
          },
          "409": {
            "description": "La politique d'examen a changé depuis expected_version. Examinez la dernière version avant de réessayer."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Supprimer le blueprint",
        "description": "Supprimer un blueprint. La suppression réussit toujours et ne modifie pas les dossiers du blueprint : les dossiers existants conservent leur référence au blueprint et ses paramètres continuent de s'appliquer à eux. Un blueprint supprimé n'apparaît plus dans les listes de blueprints et ne peut plus être choisi comme cible de transfert ; si un blueprint maker est supprimé alors qu'une résolution est en attente d'approbation à quatre yeux, une résolution rejetée laisse le dossier sur le blueprint checker.",
        "operationId": "delete_case_blueprint",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "delete",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Blueprints"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "blueprint_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "b1de0000-0000-4000-8000-000000000002"
            },
            "description": "UUID du blueprint."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/blueprints/b1de0000-0000-4000-8000-000000000002/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.cases.blueprints.delete(\n    \"b1de0000-0000-4000-8000-000000000002\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.cases.blueprints.delete(\"b1de0000-0000-4000-8000-000000000002\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nif err := client.Cases.Blueprints.Delete(ctx, \"b1de0000-0000-4000-8000-000000000002\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.cases().blueprints().delete(\"b1de0000-0000-4000-8000-000000000002\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->cases->blueprints->delete('b1de0000-0000-4000-8000-000000000002');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.blueprints.delete(\"b1de0000-0000-4000-8000-000000000002\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.Cases.Blueprints.DeleteAsync(\"b1de0000-0000-4000-8000-000000000002\");"
          }
        ],
        "responses": {
          "204": {
            "description": "Blueprint supprimé."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/blueprints/presets/": {
      "get": {
        "summary": "Lister les préréglages de blueprint",
        "description": "Lister les quatre modèles intégrés (Screening hit, AML investigation, Suspicious activity, KYC review) avec leur content_config et en précisant si chacun est déjà installé sur cette application.",
        "operationId": "list_case_blueprint_presets",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "list_presets",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Blueprints"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/blueprints/presets/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.blueprints.list_presets()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.blueprints.listPresets();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Blueprints.ListPresets(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().blueprints().listPresets();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->blueprints->listPresets();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.blueprints.list_presets\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Blueprints.ListPresetsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Catalogue de préréglages.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "preset_key": {
                            "type": "string",
                            "enum": [
                              "screening_hit",
                              "aml_investigation",
                              "suspicious_activity",
                              "kyc"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "content_config": {
                            "$ref": "#/components/schemas/CaseContentConfig"
                          },
                          "installed": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/blueprints/presets/install/": {
      "post": {
        "summary": "Installer des préréglages de blueprint",
        "description": "Copier un ou plusieurs préréglages dans l'application en tant que modèles modifiables. Idempotent par preset_key ; omettez preset_keys pour installer tous les préréglages non encore installés.",
        "operationId": "install_case_blueprint_presets",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "install_presets",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Blueprints"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "preset_keys": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "nullable": true,
                    "description": "Sous-ensemble de screening_hit, aml_investigation, suspicious_activity, kyc. Omettre pour tout installer."
                  }
                }
              },
              "example": {
                "preset_keys": [
                  "aml_investigation",
                  "kyc"
                ]
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/blueprints/presets/install/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"preset_keys\": [\"aml_investigation\", \"kyc\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.blueprints.install_presets(\n    preset_keys=[\"aml_investigation\", \"kyc\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.blueprints.installPresets({\n  preset_keys: [\"aml_investigation\", \"kyc\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Blueprints.InstallPresets(ctx, didit.CasesBlueprintsInstallPresetsParams{\n\tPresetKeys: didit.Some([]string{\"aml_investigation\", \"kyc\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.CasesBlueprintsInstallPresetsParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().blueprints().installPresets(CasesBlueprintsInstallPresetsParams.builder()\n        .presetKeys(List.of(\"aml_investigation\", \"kyc\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->blueprints->installPresets([\n    'preset_keys' => ['aml_investigation', 'kyc'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.blueprints.install_presets(preset_keys: [\"aml_investigation\", \"kyc\"])\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Blueprints.InstallPresetsAsync(new CasesBlueprintsInstallPresetsParams\n{\n    PresetKeys = new string[] { \"aml_investigation\", \"kyc\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Un ou plusieurs préréglages installés.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseBlueprintPresetInstallResult"
                }
              }
            }
          },
          "200": {
            "description": "Aucun nouveau préréglage à installer (tous les préréglages demandés existent déjà).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseBlueprintPresetInstallResult"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/report-templates/": {
      "get": {
        "summary": "Lister les modèles de rapport",
        "description": "Lister les modèles de rapport FIU pour l'application.",
        "operationId": "list_report_templates",
        "x-didit-sdk": {
          "resource": "report_templates",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Report Templates"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            },
            "description": "Taille de la page."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            },
            "description": "Décalage de départ (base zéro)."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/report-templates/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.report_templates.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.reportTemplates.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.ReportTemplates.ListAutoPaging(ctx, didit.ReportTemplatesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.reportTemplates().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->reportTemplates->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.report_templates.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.ReportTemplates.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Modèles paginés.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de lignes correspondantes, plafonné à 100 pour des raisons de performance."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReportTemplateDetail"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer un modèle de rapport",
        "description": "Créez un modèle d'en-tête goAML réutilisable par juridiction et par type de rapport. Rejeté avec une erreur 400 si l'un des champs obligatoires au niveau du modèle (rentity_id, submission_code, currency_code_local) est manquant dans field_config ; un modèle invalide ne peut pas être enregistré ni utilisé pour créer un rapport. Les champs d'en-tête propres à chaque déclaration (action, submission_date, transactions) sont appliqués lors de la validation ou de la finalisation du rapport.",
        "operationId": "create_report_template",
        "x-didit-sdk": {
          "resource": "report_templates",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Report Templates"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "jurisdiction",
                  "report_type"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "jurisdiction": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2,
                    "description": "Code pays ISO 3166-1 alpha-2, converti en majuscules lors de l'enregistrement."
                  },
                  "report_type": {
                    "type": "string",
                    "enum": [
                      "SAR",
                      "STR",
                      "CTR",
                      "TTR",
                      "UTR",
                      "IFT",
                      "CBR",
                      "TFR"
                    ]
                  },
                  "field_config": {
                    "type": "object",
                    "description": "Valeurs par défaut réutilisables des en-têtes goAML. Champs obligatoires au niveau du modèle : rentity_id, submission_code et currency_code_local (3 lettres). Facultatif : enabled_fields (quels blocs de rapport facultatifs inclure) ainsi que les valeurs par défaut pour reporting_person, location, reason et action. Les champs d'en-tête propres au dépôt (action, submission_date, transactions, jurisdiction) sont appliqués lors de la validation ou de la finalisation du rapport, et non sur le modèle."
                  }
                }
              },
              "example": {
                "name": "US SAR default",
                "jurisdiction": "US",
                "report_type": "SAR",
                "field_config": {
                  "rentity_id": "FIU-US-00123",
                  "submission_code": "E",
                  "currency_code_local": "USD"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/report-templates/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"name\": \"US SAR default\", \"jurisdiction\": \"US\", \"report_type\": \"SAR\", \"field_config\": {\"rentity_id\": \"FIU-US-00123\", \"submission_code\": \"E\", \"currency_code_local\": \"USD\"}}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.report_templates.create(\n    name=\"US SAR default\",\n    jurisdiction=\"US\",\n    report_type=\"SAR\",\n    field_config={\"rentity_id\": \"FIU-US-00123\", \"submission_code\": \"E\", \"currency_code_local\": \"USD\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.reportTemplates.create({\n  name: \"US SAR default\",\n  jurisdiction: \"US\",\n  report_type: \"SAR\",\n  field_config: { rentity_id: \"FIU-US-00123\", submission_code: \"E\", currency_code_local: \"USD\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.ReportTemplates.Create(ctx, didit.ReportTemplatesCreateParams{\n\tName:         \"US SAR default\",\n\tJurisdiction: \"US\",\n\tReportType:   \"SAR\",\n\tFieldConfig:  didit.Some(map[string]any{\"rentity_id\": \"FIU-US-00123\", \"submission_code\": \"E\", \"currency_code_local\": \"USD\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.ReportTemplatesCreateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.reportTemplates().create(ReportTemplatesCreateParams.builder()\n        .name(\"US SAR default\")\n        .jurisdiction(\"US\")\n        .reportType(ReportTemplatesCreateParams.ReportType.of(\"SAR\"))\n        .fieldConfig(Map.of(\"rentity_id\", \"FIU-US-00123\", \"submission_code\", \"E\", \"currency_code_local\", \"USD\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->reportTemplates->create([\n    'name' => 'US SAR default',\n    'jurisdiction' => 'US',\n    'report_type' => 'SAR',\n    'field_config' => ['rentity_id' => 'FIU-US-00123', 'submission_code' => 'E', 'currency_code_local' => 'USD'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.report_templates.create(\n  name: \"US SAR default\",\n  jurisdiction: \"US\",\n  report_type: \"SAR\",\n  field_config: { rentity_id: \"FIU-US-00123\", submission_code: \"E\", currency_code_local: \"USD\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.ReportTemplates.CreateAsync(new ReportTemplatesCreateParams\n{\n    Name = \"US SAR default\",\n    Jurisdiction = \"US\",\n    ReportType = \"SAR\",\n    FieldConfig = new Dictionary<string, object> { [\"rentity_id\"] = \"FIU-US-00123\", [\"submission_code\"] = \"E\", [\"currency_code_local\"] = \"USD\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Modèle créé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportTemplateDetail"
                }
              }
            }
          },
          "400": {
            "description": "Juridiction non reconnue, ou field_config échoue à la validation des champs obligatoires.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/report-templates/{template_uuid}/": {
      "get": {
        "summary": "Obtenir le modèle de rapport",
        "description": "Récupérer un modèle de rapport.",
        "operationId": "get_report_template",
        "x-didit-sdk": {
          "resource": "report_templates",
          "method": "retrieve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Report Templates"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "template_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "7ec00000-0000-4000-8000-000000000006"
            },
            "description": "UUID du modèle de rapport."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/report-templates/7ec00000-0000-4000-8000-000000000006/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.report_templates.retrieve(\n    \"7ec00000-0000-4000-8000-000000000006\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.reportTemplates.retrieve(\"7ec00000-0000-4000-8000-000000000006\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.ReportTemplates.Retrieve(ctx, \"7ec00000-0000-4000-8000-000000000006\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.reportTemplates().retrieve(\"7ec00000-0000-4000-8000-000000000006\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->reportTemplates->retrieve('7ec00000-0000-4000-8000-000000000006');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.report_templates.retrieve(\"7ec00000-0000-4000-8000-000000000006\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.ReportTemplates.RetrieveAsync(\"7ec00000-0000-4000-8000-000000000006\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détails du modèle.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportTemplateDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour le modèle de rapport",
        "description": "Mettre à jour partiellement un modèle de rapport. Valide à nouveau les champs obligatoires goAML lors de l'enregistrement.",
        "operationId": "update_report_template",
        "x-didit-sdk": {
          "resource": "report_templates",
          "method": "update",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Report Templates"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "template_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "7ec00000-0000-4000-8000-000000000006"
            },
            "description": "UUID du modèle de rapport."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "jurisdiction": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2,
                    "description": "Code pays ISO 3166-1 alpha-2, converti en majuscules lors de l'enregistrement."
                  },
                  "report_type": {
                    "type": "string",
                    "enum": [
                      "SAR",
                      "STR",
                      "CTR",
                      "TTR",
                      "UTR",
                      "IFT",
                      "CBR",
                      "TFR"
                    ]
                  },
                  "field_config": {
                    "type": "object",
                    "description": "Valeurs par défaut réutilisables des en-têtes goAML. Champs obligatoires au niveau du modèle : rentity_id, submission_code et currency_code_local (3 lettres). Facultatif : enabled_fields (quels blocs de rapport facultatifs inclure) ainsi que les valeurs par défaut pour reporting_person, location, reason et action. Les champs d'en-tête propres au dépôt (action, submission_date, transactions, jurisdiction) sont appliqués lors de la validation ou de la finalisation du rapport, et non sur le modèle."
                  }
                }
              },
              "example": {
                "field_config": {
                  "rentity_id": "FIU-US-00124"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/report-templates/7ec00000-0000-4000-8000-000000000006/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"field_config\": {\"rentity_id\": \"FIU-US-00124\"}}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.report_templates.update(\n    \"7ec00000-0000-4000-8000-000000000006\",\n    field_config={\"rentity_id\": \"FIU-US-00124\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.reportTemplates.update(\"7ec00000-0000-4000-8000-000000000006\", {\n  field_config: { rentity_id: \"FIU-US-00124\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.ReportTemplates.Update(ctx, \"7ec00000-0000-4000-8000-000000000006\", didit.ReportTemplatesUpdateParams{\n\tFieldConfig: didit.Some(map[string]any{\"rentity_id\": \"FIU-US-00124\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.ReportTemplatesUpdateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.reportTemplates().update(\"7ec00000-0000-4000-8000-000000000006\", ReportTemplatesUpdateParams.builder()\n        .fieldConfig(Map.of(\"rentity_id\", \"FIU-US-00124\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->reportTemplates->update('7ec00000-0000-4000-8000-000000000006', [\n    'field_config' => ['rentity_id' => 'FIU-US-00124'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.report_templates.update(\n  \"7ec00000-0000-4000-8000-000000000006\",\n  field_config: { rentity_id: \"FIU-US-00124\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.ReportTemplates.UpdateAsync(\"7ec00000-0000-4000-8000-000000000006\", new ReportTemplatesUpdateParams\n{\n    FieldConfig = new Dictionary<string, object> { [\"rentity_id\"] = \"FIU-US-00124\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Modèle mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportTemplateDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Supprimer le modèle de rapport",
        "description": "Supprimer un modèle de rapport. Les rapports déjà créés à partir de celui-ci ne sont pas affectés.",
        "operationId": "delete_report_template",
        "x-didit-sdk": {
          "resource": "report_templates",
          "method": "delete",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Report Templates"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "template_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "7ec00000-0000-4000-8000-000000000006"
            },
            "description": "UUID du modèle de rapport."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/report-templates/7ec00000-0000-4000-8000-000000000006/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.report_templates.delete(\n    \"7ec00000-0000-4000-8000-000000000006\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.reportTemplates.delete(\"7ec00000-0000-4000-8000-000000000006\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nif err := client.ReportTemplates.Delete(ctx, \"7ec00000-0000-4000-8000-000000000006\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.reportTemplates().delete(\"7ec00000-0000-4000-8000-000000000006\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->reportTemplates->delete('7ec00000-0000-4000-8000-000000000006');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.report_templates.delete(\"7ec00000-0000-4000-8000-000000000006\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.ReportTemplates.DeleteAsync(\"7ec00000-0000-4000-8000-000000000006\");"
          }
        ],
        "responses": {
          "204": {
            "description": "Modèle supprimé."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/regulatory-reports/": {
      "get": {
        "summary": "Lister les rapports d'un dossier",
        "description": "Lister les rapports FIU générés pour le dossier.",
        "operationId": "list_case_regulatory_reports",
        "x-didit-sdk": {
          "resource": "cases.regulatory_reports",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            },
            "description": "Taille de la page."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            },
            "description": "Décalage de départ (base zéro)."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/regulatory-reports/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.regulatory_reports.list(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.regulatoryReports.list(\"c1a5e000-0000-4000-8000-000000000001\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.RegulatoryReports.ListAutoPaging(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesRegulatoryReportsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().regulatoryReports().list(\"c1a5e000-0000-4000-8000-000000000001\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->regulatoryReports->list('c1a5e000-0000-4000-8000-000000000001') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.regulatory_reports.list(\"c1a5e000-0000-4000-8000-000000000001\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.RegulatoryReports.ListAsync(\"c1a5e000-0000-4000-8000-000000000001\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Rapports paginés pour le dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegulatoryReportList"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer un rapport à partir d'un dossier",
        "description": "Créez un brouillon de rapport FIU pour le dossier : statut DRAFT, prérempli automatiquement à partir du modèle facultatif ainsi que du sujet du dossier, des transactions liées et du descriptif. Validez puis finalisez pour générer le XML goAML et le PDF.",
        "operationId": "create_case_regulatory_report",
        "x-didit-sdk": {
          "resource": "cases.regulatory_reports",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "case_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "c1a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du dossier."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "report_type": {
                    "type": "string",
                    "enum": [
                      "SAR",
                      "STR",
                      "CTR",
                      "TTR",
                      "UTR",
                      "IFT",
                      "CBR",
                      "TFR"
                    ],
                    "description": "Requis sauf si un modèle est fourni ; le report_type du modèle est utilisé dans le cas contraire."
                  },
                  "jurisdiction": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2,
                    "description": "Requis sauf si un modèle est fourni."
                  },
                  "template": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true,
                    "description": "UUID du modèle de rapport ; son field_config initialise le brouillon avant que les données issues du dossier ne soient fusionnées."
                  },
                  "transactions": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "nullable": true,
                    "description": "Transactions à associer ; par défaut, les transactions liées au dossier."
                  },
                  "rentity_id": {
                    "type": "string",
                    "nullable": true
                  },
                  "rentity_branch": {
                    "type": "string",
                    "nullable": true
                  },
                  "submission_code": {
                    "type": "string",
                    "enum": [
                      "E",
                      "M"
                    ],
                    "default": "E"
                  },
                  "entity_reference": {
                    "type": "string",
                    "nullable": true
                  },
                  "fiu_ref_number": {
                    "type": "string",
                    "nullable": true
                  },
                  "currency_code_local": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 3,
                    "nullable": true
                  },
                  "submission_date": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  },
                  "reporting_person": {
                    "type": "object"
                  },
                  "location": {
                    "type": "object"
                  },
                  "reason": {
                    "type": "string",
                    "nullable": true
                  },
                  "action": {
                    "type": "string",
                    "nullable": true
                  },
                  "activity": {
                    "type": "string",
                    "nullable": true
                  },
                  "narrative": {
                    "type": "object",
                    "properties": {
                      "who": {
                        "type": "string"
                      },
                      "what": {
                        "type": "string"
                      },
                      "when": {
                        "type": "string"
                      },
                      "where": {
                        "type": "string"
                      },
                      "why": {
                        "type": "string"
                      },
                      "how": {
                        "type": "string"
                      }
                    }
                  },
                  "report_indicators": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "included_fields": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "template": "7ec00000-0000-4000-8000-000000000006"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/regulatory-reports/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"template\": \"7ec00000-0000-4000-8000-000000000006\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.regulatory_reports.create(\n    \"c1a5e000-0000-4000-8000-000000000001\",\n    template=\"7ec00000-0000-4000-8000-000000000006\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.regulatoryReports.create(\"c1a5e000-0000-4000-8000-000000000001\", {\n  template: \"7ec00000-0000-4000-8000-000000000006\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RegulatoryReports.Create(ctx, \"c1a5e000-0000-4000-8000-000000000001\", didit.CasesRegulatoryReportsCreateParams{\n\tTemplate: didit.String(\"7ec00000-0000-4000-8000-000000000006\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasesRegulatoryReportsCreateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().regulatoryReports().create(\"c1a5e000-0000-4000-8000-000000000001\", CasesRegulatoryReportsCreateParams.builder()\n        .template(\"7ec00000-0000-4000-8000-000000000006\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->regulatoryReports->create('c1a5e000-0000-4000-8000-000000000001', [\n    'template' => '7ec00000-0000-4000-8000-000000000006',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.regulatory_reports.create(\n  \"c1a5e000-0000-4000-8000-000000000001\",\n  template: \"7ec00000-0000-4000-8000-000000000006\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RegulatoryReports.CreateAsync(\"c1a5e000-0000-4000-8000-000000000001\", new CasesRegulatoryReportsCreateParams\n{\n    Template = \"7ec00000-0000-4000-8000-000000000006\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Brouillon de rapport créé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegulatoryReportDetail"
                }
              }
            }
          },
          "400": {
            "description": "Le modèle référencé est introuvable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/regulatory-reports/": {
      "get": {
        "summary": "Lister les rapports",
        "description": "Liste des rapports FIU à l'échelle de l'application, éventuellement filtrée par status, report_type ou case.",
        "operationId": "list_regulatory_reports",
        "x-didit-sdk": {
          "resource": "regulatory_reports",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            },
            "description": "Taille de la page."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            },
            "description": "Décalage de départ (base zéro)."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DRAFT",
                "VALIDATED",
                "FINALIZED"
              ]
            },
            "description": "Filtrer par statut."
          },
          {
            "name": "report_type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "SAR",
                "STR",
                "CTR",
                "TTR",
                "UTR",
                "IFT",
                "CBR",
                "TFR"
              ]
            },
            "description": "Filtrer par type de rapport."
          },
          {
            "name": "case",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filtrer selon les rapports associés à ce dossier."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.regulatory_reports.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.regulatoryReports.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.RegulatoryReports.ListAutoPaging(ctx, didit.RegulatoryReportsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.regulatoryReports().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->regulatoryReports->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.regulatory_reports.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.RegulatoryReports.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Rapports paginés sur l'ensemble de l'application.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegulatoryReportList"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer un rapport autonome",
        "description": "Créez un brouillon de rapport FIU depuis la page Rapports indépendante : le dossier et le modèle sont tous deux obligatoires (contrairement à la création dans le cadre d'un dossier, qui peut omettre le modèle).",
        "operationId": "create_standalone_regulatory_report",
        "x-didit-sdk": {
          "resource": "regulatory_reports",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "case",
                  "template"
                ],
                "properties": {
                  "case": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "template": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "report_type": {
                    "type": "string",
                    "enum": [
                      "SAR",
                      "STR",
                      "CTR",
                      "TTR",
                      "UTR",
                      "IFT",
                      "CBR",
                      "TFR"
                    ],
                    "description": "Requis sauf si un modèle est fourni ; le report_type du modèle est utilisé dans le cas contraire."
                  },
                  "jurisdiction": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2,
                    "description": "Requis sauf si un modèle est fourni."
                  },
                  "transactions": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "nullable": true,
                    "description": "Transactions à associer ; par défaut, les transactions liées au dossier."
                  },
                  "rentity_id": {
                    "type": "string",
                    "nullable": true
                  },
                  "rentity_branch": {
                    "type": "string",
                    "nullable": true
                  },
                  "submission_code": {
                    "type": "string",
                    "enum": [
                      "E",
                      "M"
                    ],
                    "default": "E"
                  },
                  "entity_reference": {
                    "type": "string",
                    "nullable": true
                  },
                  "fiu_ref_number": {
                    "type": "string",
                    "nullable": true
                  },
                  "currency_code_local": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 3,
                    "nullable": true
                  },
                  "submission_date": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  },
                  "reporting_person": {
                    "type": "object"
                  },
                  "location": {
                    "type": "object"
                  },
                  "reason": {
                    "type": "string",
                    "nullable": true
                  },
                  "action": {
                    "type": "string",
                    "nullable": true
                  },
                  "activity": {
                    "type": "string",
                    "nullable": true
                  },
                  "narrative": {
                    "type": "object",
                    "properties": {
                      "who": {
                        "type": "string"
                      },
                      "what": {
                        "type": "string"
                      },
                      "when": {
                        "type": "string"
                      },
                      "where": {
                        "type": "string"
                      },
                      "why": {
                        "type": "string"
                      },
                      "how": {
                        "type": "string"
                      }
                    }
                  },
                  "report_indicators": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "included_fields": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "case": "c1a5e000-0000-4000-8000-000000000001",
                "template": "7ec00000-0000-4000-8000-000000000006"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"case\": \"c1a5e000-0000-4000-8000-000000000001\", \"template\": \"7ec00000-0000-4000-8000-000000000006\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.regulatory_reports.create(\n    case=\"c1a5e000-0000-4000-8000-000000000001\",\n    template=\"7ec00000-0000-4000-8000-000000000006\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.regulatoryReports.create({\n  case: \"c1a5e000-0000-4000-8000-000000000001\",\n  template: \"7ec00000-0000-4000-8000-000000000006\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.RegulatoryReports.Create(ctx, didit.RegulatoryReportsCreateParams{\n\tCase:     \"c1a5e000-0000-4000-8000-000000000001\",\n\tTemplate: \"7ec00000-0000-4000-8000-000000000006\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.RegulatoryReportsCreateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.regulatoryReports().create(RegulatoryReportsCreateParams.builder()\n        .case_(\"c1a5e000-0000-4000-8000-000000000001\")\n        .template(\"7ec00000-0000-4000-8000-000000000006\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->regulatoryReports->create([\n    'case' => 'c1a5e000-0000-4000-8000-000000000001',\n    'template' => '7ec00000-0000-4000-8000-000000000006',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.regulatory_reports.create(\n  case: \"c1a5e000-0000-4000-8000-000000000001\",\n  template: \"7ec00000-0000-4000-8000-000000000006\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.RegulatoryReports.CreateAsync(new RegulatoryReportsCreateParams\n{\n    Case = \"c1a5e000-0000-4000-8000-000000000001\",\n    Template = \"7ec00000-0000-4000-8000-000000000006\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Brouillon de rapport créé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegulatoryReportDetail"
                }
              }
            }
          },
          "400": {
            "description": "Le modèle référencé est introuvable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/regulatory-reports/{report_uuid}/": {
      "get": {
        "summary": "Obtenir le rapport",
        "description": "Récupérer un rapport réglementaire.",
        "operationId": "get_regulatory_report",
        "x-didit-sdk": {
          "resource": "regulatory_reports",
          "method": "retrieve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "report_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "5ec00000-0000-4000-8000-000000000007"
            },
            "description": "UUID du rapport."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/5ec00000-0000-4000-8000-000000000007/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.regulatory_reports.retrieve(\n    \"5ec00000-0000-4000-8000-000000000007\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.regulatoryReports.retrieve(\"5ec00000-0000-4000-8000-000000000007\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.RegulatoryReports.Retrieve(ctx, \"5ec00000-0000-4000-8000-000000000007\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.regulatoryReports().retrieve(\"5ec00000-0000-4000-8000-000000000007\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->regulatoryReports->retrieve('5ec00000-0000-4000-8000-000000000007');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.regulatory_reports.retrieve(\"5ec00000-0000-4000-8000-000000000007\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.RegulatoryReports.RetrieveAsync(\"5ec00000-0000-4000-8000-000000000007\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détail du rapport.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegulatoryReportDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour le rapport",
        "description": "Modifier les champs d'un rapport à l'état de brouillon ou validé. Les rapports finalisés ne peuvent pas être modifiés (409).",
        "operationId": "update_regulatory_report",
        "x-didit-sdk": {
          "resource": "regulatory_reports",
          "method": "update",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "report_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "5ec00000-0000-4000-8000-000000000007"
            },
            "description": "UUID du rapport."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "jurisdiction": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2
                  },
                  "rentity_id": {
                    "type": "string",
                    "nullable": true
                  },
                  "rentity_branch": {
                    "type": "string",
                    "nullable": true
                  },
                  "submission_code": {
                    "type": "string",
                    "enum": [
                      "E",
                      "M"
                    ],
                    "default": "E"
                  },
                  "entity_reference": {
                    "type": "string",
                    "nullable": true
                  },
                  "fiu_ref_number": {
                    "type": "string",
                    "nullable": true
                  },
                  "currency_code_local": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 3,
                    "nullable": true
                  },
                  "submission_date": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  },
                  "reporting_person": {
                    "type": "object"
                  },
                  "location": {
                    "type": "object"
                  },
                  "reason": {
                    "type": "string",
                    "nullable": true
                  },
                  "action": {
                    "type": "string",
                    "nullable": true
                  },
                  "activity": {
                    "type": "string",
                    "nullable": true
                  },
                  "narrative": {
                    "type": "object",
                    "properties": {
                      "who": {
                        "type": "string"
                      },
                      "what": {
                        "type": "string"
                      },
                      "when": {
                        "type": "string"
                      },
                      "where": {
                        "type": "string"
                      },
                      "why": {
                        "type": "string"
                      },
                      "how": {
                        "type": "string"
                      }
                    }
                  },
                  "report_indicators": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "included_fields": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "rentity_id": "FIU-US-00123",
                "currency_code_local": "USD"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/5ec00000-0000-4000-8000-000000000007/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"rentity_id\": \"FIU-US-00123\", \"currency_code_local\": \"USD\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.regulatory_reports.update(\n    \"5ec00000-0000-4000-8000-000000000007\",\n    rentity_id=\"FIU-US-00123\",\n    currency_code_local=\"USD\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.regulatoryReports.update(\"5ec00000-0000-4000-8000-000000000007\", {\n  rentity_id: \"FIU-US-00123\",\n  currency_code_local: \"USD\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.RegulatoryReports.Update(ctx, \"5ec00000-0000-4000-8000-000000000007\", didit.RegulatoryReportsUpdateParams{\n\tRentityID:         didit.String(\"FIU-US-00123\"),\n\tCurrencyCodeLocal: didit.String(\"USD\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.RegulatoryReportsUpdateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.regulatoryReports().update(\"5ec00000-0000-4000-8000-000000000007\", RegulatoryReportsUpdateParams.builder()\n        .rentityId(\"FIU-US-00123\")\n        .currencyCodeLocal(\"USD\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->regulatoryReports->update('5ec00000-0000-4000-8000-000000000007', [\n    'rentity_id' => 'FIU-US-00123',\n    'currency_code_local' => 'USD',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.regulatory_reports.update(\n  \"5ec00000-0000-4000-8000-000000000007\",\n  rentity_id: \"FIU-US-00123\",\n  currency_code_local: \"USD\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.RegulatoryReports.UpdateAsync(\"5ec00000-0000-4000-8000-000000000007\", new RegulatoryReportsUpdateParams\n{\n    RentityId = \"FIU-US-00123\",\n    CurrencyCodeLocal = \"USD\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Rapport mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegulatoryReportDetail"
                }
              }
            }
          },
          "409": {
            "description": "Le rapport est déjà finalisé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Supprimer le rapport",
        "description": "Supprimer définitivement un rapport réglementaire. Le rapport, son narratif copié et ses motifs, ses liens de transaction ainsi que son XML goAML et son PDF générés sont effacés, y compris chaque version stockée de ces fichiers. Le rapport disparaît des listes et les URL de téléchargement cessent de fonctionner. Les autres enregistrements, notamment le dossier, les transactions, les personnes et les entreprises, ne sont pas supprimés. Aucun retour en arrière n'est possible.\n\nUn rapport au statut de brouillon ou validé peut être supprimé sans corps de requête. La suppression d'un rapport finalisé nécessite `confirm_delete: true` dans le corps de la requête. Si le rapport est introuvable, la requête renvoie `404` ; si un rapport finalisé est envoyé sans confirmation, elle renvoie `400` et rien n'est supprimé.",
        "operationId": "delete_regulatory_report",
        "x-didit-sdk": {
          "resource": "regulatory_reports",
          "method": "delete",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "report_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "5ec00000-0000-4000-8000-000000000007"
            },
            "description": "UUID du rapport."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl (draft report)",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/5ec00000-0000-4000-8000-000000000007/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "curl",
            "label": "curl (finalized report)",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/5ec00000-0000-4000-8000-000000000007/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"confirm_delete\": true}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.regulatory_reports.delete(\n    \"5ec00000-0000-4000-8000-000000000007\",\n    confirm_delete=True,\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.regulatoryReports.delete(\"5ec00000-0000-4000-8000-000000000007\", {\n  confirm_delete: true,\n});"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.RegulatoryReportsDeleteParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.regulatoryReports().delete(\"5ec00000-0000-4000-8000-000000000007\", RegulatoryReportsDeleteParams.builder()\n        .confirmDelete(true)\n        .build());"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->regulatoryReports->delete('5ec00000-0000-4000-8000-000000000007', [\n    'confirm_delete' => true,\n]);"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.regulatory_reports.delete(\n  \"5ec00000-0000-4000-8000-000000000007\",\n  confirm_delete: true\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.RegulatoryReports.DeleteAsync(\"5ec00000-0000-4000-8000-000000000007\", new RegulatoryReportsDeleteParams\n{\n    ConfirmDelete = true,\n});"
          }
        ],
        "responses": {
          "204": {
            "description": "Rapport supprimé, y compris ses fichiers générés."
          },
          "400": {
            "description": "Un rapport finalisé a été envoyé sans `confirm_delete: true`. Rien n'est supprimé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "confirm_delete": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "example": {
                  "confirm_delete": [
                    "This field is required to delete a finalized report."
                  ]
                }
              }
            }
          },
          "403": {
            "description": "La clé API ne peut pas supprimer de rapports. L'endpoint requiert `write:cases`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Rapport introuvable dans cette application.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Le rapport est déjà en cours de suppression. Réessayez la requête pour terminer l'effacement de ses fichiers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "This report is being deleted. Retry deleting it to finish erasing its files.",
                  "code": "report_deletion_pending"
                }
              }
            }
          },
          "503": {
            "description": "Les fichiers du rapport n'ont pas pu être effacés pour le moment. Le rapport est toujours en place. Réessayez la requête.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "The report files could not be erased. Please retry deleting the report.",
                  "code": "report_storage_unavailable"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Requis uniquement pour un rapport finalisé.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm_delete": {
                    "type": "boolean",
                    "description": "Définir sur true pour confirmer qu'un rapport finalisé et ses fichiers générés sont définitivement supprimés."
                  }
                },
                "example": {
                  "confirm_delete": true
                }
              },
              "example": {
                "confirm_delete": true
              }
            }
          }
        }
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/regulatory-reports/{report_uuid}/validate/": {
      "post": {
        "summary": "Valider le rapport",
        "description": "Vérifie le rapport par rapport aux champs d'en-tête obligatoires de goAML (identifiant de l'entité déclarante, code de soumission, devise locale, action entreprise, date de soumission), ainsi qu'au moins une transaction jointe et une juridiction à 2 lettres, sans générer de fichiers. Enregistre également le résultat sur le rapport : validation_errors et validated_at sont mis à jour, et le statut d'un rapport non finalisé passe à VALIDATED (aucune erreur) ou revient à DRAFT (erreurs).",
        "operationId": "validate_regulatory_report",
        "x-didit-sdk": {
          "resource": "regulatory_reports",
          "method": "validate",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "report_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "5ec00000-0000-4000-8000-000000000007"
            },
            "description": "UUID du rapport."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/5ec00000-0000-4000-8000-000000000007/validate/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.regulatory_reports.validate(\n    \"5ec00000-0000-4000-8000-000000000007\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.regulatoryReports.validate(\"5ec00000-0000-4000-8000-000000000007\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.RegulatoryReports.Validate(ctx, \"5ec00000-0000-4000-8000-000000000007\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.regulatoryReports().validate(\"5ec00000-0000-4000-8000-000000000007\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->regulatoryReports->validate('5ec00000-0000-4000-8000-000000000007');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.regulatory_reports.validate(\"5ec00000-0000-4000-8000-000000000007\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.RegulatoryReports.ValidateAsync(\"5ec00000-0000-4000-8000-000000000007\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat de la validation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "DRAFT",
                        "VALIDATED",
                        "FINALIZED"
                      ]
                    },
                    "is_valid": {
                      "type": "boolean"
                    },
                    "errors": {
                      "type": "array",
                      "description": "Vide lorsque valide.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "field": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/regulatory-reports/{report_uuid}/finalize/": {
      "post": {
        "summary": "Finaliser le rapport",
        "description": "Valider à nouveau, puis générer le XML goAML et le PDF et les téléverser tous deux vers S3. Pour les rapports SAR/STR/TFR, cette action fait également passer les alertes de transaction du dossier du statut SAR en attente au statut SAR déposé.",
        "operationId": "finalize_regulatory_report",
        "x-didit-sdk": {
          "resource": "regulatory_reports",
          "method": "finalize",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "report_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "5ec00000-0000-4000-8000-000000000007"
            },
            "description": "UUID du rapport."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/5ec00000-0000-4000-8000-000000000007/finalize/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.regulatory_reports.finalize(\n    \"5ec00000-0000-4000-8000-000000000007\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.regulatoryReports.finalize(\"5ec00000-0000-4000-8000-000000000007\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.RegulatoryReports.Finalize(ctx, \"5ec00000-0000-4000-8000-000000000007\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.regulatoryReports().finalize_(\"5ec00000-0000-4000-8000-000000000007\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->regulatoryReports->finalize('5ec00000-0000-4000-8000-000000000007');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.regulatory_reports.finalize(\"5ec00000-0000-4000-8000-000000000007\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.RegulatoryReports.FinalizeAsync(\"5ec00000-0000-4000-8000-000000000007\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Rapport finalisé ; xml_s3_key et pdf_s3_key sont définis.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegulatoryReportDetail"
                }
              }
            }
          },
          "400": {
            "description": "Échec de validation du rapport.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "field": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Le rapport n'est pas dans un état finalisable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/regulatory-reports/{report_uuid}/download-url/": {
      "get": {
        "summary": "Obtenir l'URL de téléchargement du rapport",
        "description": "Générer une URL pré-signée pour le fichier XML goAML ou le PDF d'un rapport finalisé.",
        "operationId": "get_regulatory_report_download_url",
        "x-didit-sdk": {
          "resource": "regulatory_reports",
          "method": "retrieve_download_url",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Regulatory Reports"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "report_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "5ec00000-0000-4000-8000-000000000007"
            },
            "description": "UUID du rapport."
          },
          {
            "name": "file",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pdf",
                "xml"
              ],
              "default": "pdf"
            },
            "description": "Quel fichier télécharger."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/regulatory-reports/5ec00000-0000-4000-8000-000000000007/download-url/?file=xml' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.regulatory_reports.retrieve_download_url(\n    \"5ec00000-0000-4000-8000-000000000007\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.regulatoryReports.retrieveDownloadUrl(\"5ec00000-0000-4000-8000-000000000007\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.RegulatoryReports.RetrieveDownloadURL(ctx, \"5ec00000-0000-4000-8000-000000000007\", didit.RegulatoryReportsRetrieveDownloadURLParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.regulatoryReports().retrieveDownloadUrl(\"5ec00000-0000-4000-8000-000000000007\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->regulatoryReports->retrieveDownloadUrl('5ec00000-0000-4000-8000-000000000007');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.regulatory_reports.retrieve_download_url(\"5ec00000-0000-4000-8000-000000000007\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.RegulatoryReports.RetrieveDownloadUrlAsync(\"5ec00000-0000-4000-8000-000000000007\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "URL de téléchargement pré-signée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "download_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "file": {
                      "type": "string",
                      "enum": [
                        "pdf",
                        "xml"
                      ]
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Le rapport n'est pas encore finalisé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/transactions/rules/": {
      "get": {
        "summary": "Lister les règles",
        "description": "Lister les règles de surveillance des transactions de l'application : vos règles personnalisées ainsi que tous les modèles prédéfinis de la bibliothèque que vous avez installés. Filtrez par source, catégorie, mode, pack ou recherche en texte libre ; triez avec `ordering` (run_count, approved_pct, reviewed_pct, declined_pct, latest_triggered_at, title, created_at, source, chacun acceptant un préfixe facultatif `-`).",
        "operationId": "listTransactionRules",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "PRESET",
                "CUSTOM"
              ]
            },
            "description": "PRESET ou CUSTOM"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filtrer par catégorie de règle"
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ACTIVE",
                "DISABLED",
                "TEST"
              ]
            },
            "description": "ACTIVE, DISABLED ou TEST"
          },
          {
            "name": "bundle",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filtrer les préréglages par lot"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Correspondance insensible à la casse avec le titre et la description"
          },
          {
            "name": "ordering",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Champs de tri séparés par des virgules, par défaut source,-run_count"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Taille de la page"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Décalage de page"
          }
        ],
        "responses": {
          "200": {
            "description": "Règles paginées.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TransactionRuleDetail"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/transactions/rules/?source=CUSTOM&ordering=-run_count' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.transactions.rules.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.transactions.rules.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Transactions.Rules.ListAutoPaging(ctx, didit.TransactionsRulesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.transactions().rules().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->transactions->rules->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.transactions.rules.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Transactions.Rules.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "summary": "Créer une règle",
        "description": "Créez une règle personnalisée (CUSTOM) de surveillance des transactions. Les titres sont uniques par application (doublon -> 400). Une action `change_status` ciblant `AWAITING_USER` doit comporter un `workflow_id`. Les règles créées en mode ACTIVE s'appliquent immédiatement aux nouvelles transactions - le workflow recommandé consiste à créer en mode TEST, effectuer un backtest, puis basculer le mode sur ACTIVE. Pour modifier une règle de la bibliothèque, créez-la sous forme de copie : envoyez la définition de la règle de la bibliothèque avec `metadata.based_on` (sa clé de bibliothèque) et `metadata.based_on_rule_uuid`.",
        "operationId": "createTransactionRule",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionRuleCreateRequest"
              },
              "example": {
                "title": "Structuring - inbound (custom)",
                "description": "20+ inbound EUR transfers, all under 10,000 EUR, 30 days",
                "category": "finance",
                "mode": "TEST",
                "evaluation_mode": "ALL",
                "scope": {
                  "transaction_types": [
                    "finance"
                  ],
                  "directions": [
                    "INBOUND"
                  ]
                },
                "conditions": [
                  {
                    "field": "currency",
                    "operator": "eq",
                    "value": "EUR"
                  },
                  {
                    "field": "amount",
                    "operator": "lt",
                    "value": 10000
                  }
                ],
                "aggregation": [
                  {
                    "metric": "count",
                    "operator": "gte",
                    "value": 20,
                    "window": "30d",
                    "filters": {
                      "direction": "INBOUND",
                      "transaction_type": "finance",
                      "subject_vendor_data": "__current__",
                      "currency": "EUR"
                    }
                  },
                  {
                    "metric": "max",
                    "field": "amount",
                    "operator": "lt",
                    "value": 10000,
                    "window": "30d",
                    "filters": {
                      "direction": "INBOUND",
                      "transaction_type": "finance",
                      "subject_vendor_data": "__current__",
                      "currency": "EUR"
                    }
                  }
                ],
                "actions": [
                  {
                    "type": "add_score",
                    "value": 35
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "La règle créée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionRuleDetail"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation - titre en doublon, opérateur/métrique inconnu(e), fenêtre mal formée, direction de portée invalide ou AWAITING_USER sans workflow_id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "title": [
                    "A rule with this name already exists."
                  ]
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/transactions/rules/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"title\": \"Structuring - inbound (custom)\", \"description\": \"20+ inbound EUR transfers, all under 10,000 EUR, 30 days\", \"category\": \"finance\", \"mode\": \"TEST\", \"evaluation_mode\": \"ALL\", \"scope\": {\"transaction_types\": [\"finance\"], \"directions\": [\"INBOUND\"]}, \"conditions\": [{\"field\": \"currency\", \"operator\": \"eq\", \"value\": \"EUR\"}, {\"field\": \"amount\", \"operator\": \"lt\", \"value\": 10000}], \"aggregation\": [{\"metric\": \"count\", \"operator\": \"gte\", \"value\": 20, \"window\": \"30d\", \"filters\": {\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"}}, {\"metric\": \"max\", \"field\": \"amount\", \"operator\": \"lt\", \"value\": 10000, \"window\": \"30d\", \"filters\": {\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"}}], \"actions\": [{\"type\": \"add_score\", \"value\": 35}]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.rules.create(\n    title=\"Structuring - inbound (custom)\",\n    description=\"20+ inbound EUR transfers, all under 10,000 EUR, 30 days\",\n    category=\"finance\",\n    mode=\"TEST\",\n    evaluation_mode=\"ALL\",\n    scope={\n        \"transaction_types\": [\"finance\"],\n        \"directions\": [\"INBOUND\"],\n    },\n    conditions=[{\n        \"field\": \"currency\",\n        \"operator\": \"eq\",\n        \"value\": \"EUR\",\n    }, {\n        \"field\": \"amount\",\n        \"operator\": \"lt\",\n        \"value\": 10000,\n    }],\n    aggregation=[{\n        \"metric\": \"count\",\n        \"operator\": \"gte\",\n        \"value\": 20.0,\n        \"window\": \"30d\",\n        \"filters\": {\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"},\n    }, {\n        \"metric\": \"max\",\n        \"field\": \"amount\",\n        \"operator\": \"lt\",\n        \"value\": 10000.0,\n        \"window\": \"30d\",\n        \"filters\": {\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"},\n    }],\n    actions=[{\n        \"type\": \"add_score\",\n        \"value\": 35,\n    }],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.rules.create({\n  title: \"Structuring - inbound (custom)\",\n  description: \"20+ inbound EUR transfers, all under 10,000 EUR, 30 days\",\n  category: \"finance\",\n  mode: \"TEST\",\n  evaluation_mode: \"ALL\",\n  scope: {\n    transaction_types: [\"finance\"],\n    directions: [\"INBOUND\"],\n  },\n  conditions: [{\n    field: \"currency\",\n    operator: \"eq\",\n    value: \"EUR\",\n  }, {\n    field: \"amount\",\n    operator: \"lt\",\n    value: 10000,\n  }],\n  aggregation: [{\n    metric: \"count\",\n    operator: \"gte\",\n    value: 20.0,\n    window: \"30d\",\n    filters: { direction: \"INBOUND\", transaction_type: \"finance\", subject_vendor_data: \"__current__\", currency: \"EUR\" },\n  }, {\n    metric: \"max\",\n    field: \"amount\",\n    operator: \"lt\",\n    value: 10000.0,\n    window: \"30d\",\n    filters: { direction: \"INBOUND\", transaction_type: \"finance\", subject_vendor_data: \"__current__\", currency: \"EUR\" },\n  }],\n  actions: [{\n    type: \"add_score\",\n    value: 35,\n  }],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Rules.Create(ctx, didit.TransactionRuleCreateRequest{\n\tTitle:          \"Structuring - inbound (custom)\",\n\tDescription:    didit.String(\"20+ inbound EUR transfers, all under 10,000 EUR, 30 days\"),\n\tCategory:       \"finance\",\n\tMode:           \"TEST\",\n\tEvaluationMode: didit.Some(didit.TransactionRuleCreateRequestEvaluationMode(\"ALL\")),\n\tScope: didit.Some(didit.TransactionRuleScopeParam{\n\t\tTransactionTypes: didit.Some([]string{\"finance\"}),\n\t\tDirections:       didit.Some([]didit.TransactionRuleScopeDirections{\"INBOUND\"}),\n\t}),\n\tConditions: didit.Some([]didit.TransactionRuleConditionParam{{\n\t\tField:    \"currency\",\n\t\tOperator: \"eq\",\n\t\tValue:    didit.Some[any](\"EUR\"),\n\t}, {\n\t\tField:    \"amount\",\n\t\tOperator: \"lt\",\n\t\tValue:    didit.Some[any](10000),\n\t}}),\n\tAggregation: didit.Some([]didit.TransactionRuleAggregationParam{{\n\t\tMetric:   didit.Some(didit.TransactionRuleAggregationMetric(\"count\")),\n\t\tOperator: didit.Some(didit.TransactionRuleAggregationOperator(\"gte\")),\n\t\tValue:    20.0,\n\t\tWindow:   didit.String(\"30d\"),\n\t\tFilters:  didit.Some(map[string]any{\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"}),\n\t}, {\n\t\tMetric:   didit.Some(didit.TransactionRuleAggregationMetric(\"max\")),\n\t\tField:    didit.String(\"amount\"),\n\t\tOperator: didit.Some(didit.TransactionRuleAggregationOperator(\"lt\")),\n\t\tValue:    10000.0,\n\t\tWindow:   didit.String(\"30d\"),\n\t\tFilters:  didit.Some(map[string]any{\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"}),\n\t}}),\n\tActions: didit.Some([]didit.TransactionRuleActionParam{{\n\t\tType:  \"add_score\",\n\t\tValue: didit.Some[any](35),\n\t}}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.TransactionRuleAction;\nimport me.didit.types.TransactionRuleActionAddScore;\nimport me.didit.types.TransactionRuleAggregation;\nimport me.didit.types.TransactionRuleCondition;\nimport me.didit.types.TransactionRuleCreateRequest;\nimport me.didit.types.TransactionRuleScope;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().rules().create(TransactionRuleCreateRequest.builder()\n        .title(\"Structuring - inbound (custom)\")\n        .description(\"20+ inbound EUR transfers, all under 10,000 EUR, 30 days\")\n        .category(\"finance\")\n        .mode(TransactionRuleCreateRequest.Mode.of(\"TEST\"))\n        .evaluationMode(TransactionRuleCreateRequest.EvaluationMode.of(\"ALL\"))\n        .scope(TransactionRuleScope.builder()\n                .transactionTypes(List.of(\"finance\"))\n                .directions(List.of(TransactionRuleScope.Directions.of(\"INBOUND\")))\n                .build())\n        .conditions(List.of(\n                TransactionRuleCondition.builder()\n                        .field(\"currency\")\n                        .operator(TransactionRuleCondition.Operator.of(\"eq\"))\n                        .value(\"EUR\")\n                        .build(),\n                TransactionRuleCondition.builder()\n                        .field(\"amount\")\n                        .operator(TransactionRuleCondition.Operator.of(\"lt\"))\n                        .value(10000)\n                        .build()))\n        .aggregation(List.of(\n                TransactionRuleAggregation.builder()\n                        .metric(TransactionRuleAggregation.Metric.of(\"count\"))\n                        .operator(TransactionRuleAggregation.Operator.of(\"gte\"))\n                        .value(20.0)\n                        .window(\"30d\")\n                        .filters(Map.of(\"direction\", \"INBOUND\", \"transaction_type\", \"finance\", \"subject_vendor_data\", \"__current__\", \"currency\", \"EUR\"))\n                        .build(),\n                TransactionRuleAggregation.builder()\n                        .metric(TransactionRuleAggregation.Metric.of(\"max\"))\n                        .field(\"amount\")\n                        .operator(TransactionRuleAggregation.Operator.of(\"lt\"))\n                        .value(10000.0)\n                        .window(\"30d\")\n                        .filters(Map.of(\"direction\", \"INBOUND\", \"transaction_type\", \"finance\", \"subject_vendor_data\", \"__current__\", \"currency\", \"EUR\"))\n                        .build()))\n        .actions(List.of(TransactionRuleAction.ofAddScore(TransactionRuleActionAddScore.builder()\n                .type(TransactionRuleActionAddScore.Type.of(\"add_score\"))\n                .value(35L)\n                .build())))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->rules->create([\n    'title' => 'Structuring - inbound (custom)',\n    'description' => '20+ inbound EUR transfers, all under 10,000 EUR, 30 days',\n    'category' => 'finance',\n    'mode' => 'TEST',\n    'evaluation_mode' => 'ALL',\n    'scope' => [\n        'transaction_types' => ['finance'],\n        'directions' => ['INBOUND'],\n    ],\n    'conditions' => [[\n        'field' => 'currency',\n        'operator' => 'eq',\n        'value' => 'EUR',\n    ], [\n        'field' => 'amount',\n        'operator' => 'lt',\n        'value' => 10000,\n    ]],\n    'aggregation' => [[\n        'metric' => 'count',\n        'operator' => 'gte',\n        'value' => 20.0,\n        'window' => '30d',\n        'filters' => ['direction' => 'INBOUND', 'transaction_type' => 'finance', 'subject_vendor_data' => '__current__', 'currency' => 'EUR'],\n    ], [\n        'metric' => 'max',\n        'field' => 'amount',\n        'operator' => 'lt',\n        'value' => 10000.0,\n        'window' => '30d',\n        'filters' => ['direction' => 'INBOUND', 'transaction_type' => 'finance', 'subject_vendor_data' => '__current__', 'currency' => 'EUR'],\n    ]],\n    'actions' => [[\n        'type' => 'add_score',\n        'value' => 35,\n    ]],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.rules.create(\n  title: \"Structuring - inbound (custom)\",\n  description: \"20+ inbound EUR transfers, all under 10,000 EUR, 30 days\",\n  category: \"finance\",\n  mode: \"TEST\",\n  evaluation_mode: \"ALL\",\n  scope: {\n    transaction_types: [\"finance\"],\n    directions: [\"INBOUND\"],\n  },\n  conditions: [{\n    field: \"currency\",\n    operator: \"eq\",\n    value: \"EUR\",\n  }, {\n    field: \"amount\",\n    operator: \"lt\",\n    value: 10000,\n  }],\n  aggregation: [{\n    metric: \"count\",\n    operator: \"gte\",\n    value: 20.0,\n    window: \"30d\",\n    filters: { direction: \"INBOUND\", transaction_type: \"finance\", subject_vendor_data: \"__current__\", currency: \"EUR\" },\n  }, {\n    metric: \"max\",\n    field: \"amount\",\n    operator: \"lt\",\n    value: 10000.0,\n    window: \"30d\",\n    filters: { direction: \"INBOUND\", transaction_type: \"finance\", subject_vendor_data: \"__current__\", currency: \"EUR\" },\n  }],\n  actions: [{\n    type: \"add_score\",\n    value: 35,\n  }]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.Rules.CreateAsync(new TransactionRuleCreateRequest\n{\n    Title = \"Structuring - inbound (custom)\",\n    Description = \"20+ inbound EUR transfers, all under 10,000 EUR, 30 days\",\n    Category = \"finance\",\n    Mode = \"TEST\",\n    EvaluationMode = new TransactionRuleCreateRequestEvaluationMode(\"ALL\"),\n    Scope = new TransactionRuleScope\n    {\n        TransactionTypes = new string[] { \"finance\" },\n        Directions = new TransactionRuleScopeDirections[] { \"INBOUND\" },\n    },\n    Conditions = new TransactionRuleCondition[]\n    {\n        new()\n        {\n            Field = \"currency\",\n            Operator = \"eq\",\n            Value = \"EUR\",\n        },\n        new()\n        {\n            Field = \"amount\",\n            Operator = \"lt\",\n            Value = 10000,\n        },\n    },\n    Aggregation = new TransactionRuleAggregation[]\n    {\n        new()\n        {\n            Metric = new TransactionRuleAggregationMetric(\"count\"),\n            Operator = new TransactionRuleAggregationOperator(\"gte\"),\n            Value = 20.0,\n            Window = \"30d\",\n            Filters = new Dictionary<string, object> { [\"direction\"] = \"INBOUND\", [\"transaction_type\"] = \"finance\", [\"subject_vendor_data\"] = \"__current__\", [\"currency\"] = \"EUR\" },\n        },\n        new()\n        {\n            Metric = new TransactionRuleAggregationMetric(\"max\"),\n            Field = \"amount\",\n            Operator = new TransactionRuleAggregationOperator(\"lt\"),\n            Value = 10000.0,\n            Window = \"30d\",\n            Filters = new Dictionary<string, object> { [\"direction\"] = \"INBOUND\", [\"transaction_type\"] = \"finance\", [\"subject_vendor_data\"] = \"__current__\", [\"currency\"] = \"EUR\" },\n        },\n    },\n    Actions = new TransactionRuleAction[]\n    {\n        new()\n        {\n            Type = new TransactionRuleActionType(\"add_score\"),\n            Value = 35,\n        },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/transactions/rules/{rule_uuid}/": {
      "parameters": [
        {
          "name": "rule_uuid",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "description": "L'uuid de la règle issu de la liste ou de la création."
        }
      ],
      "get": {
        "summary": "Obtenir la règle",
        "description": "Récupérer une règle avec sa configuration complète et ses compteurs d'exécution.",
        "operationId": "getTransactionRule",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "La règle.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionRuleDetail"
                }
              }
            }
          },
          "404": {
            "description": "Aucune règle de ce type sur cette application.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/transactions/rules/RULE_UUID/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.rules.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.rules.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Rules.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().rules().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->rules->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.rules.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.Rules.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour la règle",
        "description": "Mettre à jour partiellement une règle. Les règles personnalisées acceptent chaque champ de configuration. Les règles de la bibliothèque (PRESET) n'acceptent que `mode` : utilisez-le pour activer, désactiver ou basculer un préréglage sur TEST ; tout autre champ renvoie 400, car Didit gère les règles de la bibliothèque et applique automatiquement leurs mises à jour. Pour modifier les conditions d'une règle de la bibliothèque, créez une copie personnalisée avec `POST /v3/transactions/rules/` en utilisant la définition de la règle de la bibliothèque ainsi que `metadata.based_on` (la clé de bibliothèque) et `metadata.based_on_rule_uuid`, puis désactivez la règle de la bibliothèque avec `mode: DISABLED` afin qu'une transaction ne génère pas d'alerte deux fois. Une copie installée d'une règle de la bibliothèque suspendue est désactivée : définir son `mode` sur toute valeur autre que `DISABLED` renvoie 400 (\"This library rule cannot run yet: its conditions read data the rules engine cannot evaluate.\").",
        "operationId": "updateTransactionRule",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionRuleUpdateRequest"
              },
              "example": {
                "mode": "ACTIVE"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "La règle mise à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionRuleDetail"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation, champ autre que mode sur une règle de bibliothèque, ou mode autre que DISABLED sur une règle de bibliothèque retenue.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/transactions/rules/RULE_UUID/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"mode\": \"ACTIVE\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.rules.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    mode=\"ACTIVE\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.rules.update(\"11111111-2222-3333-4444-555555555555\", {\n  mode: \"ACTIVE\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Rules.Update(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TransactionRuleUpdateRequest{\n\tMode: didit.Some(didit.TransactionRuleUpdateRequestMode(\"ACTIVE\")),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TransactionRuleUpdateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().rules().update(\"11111111-2222-3333-4444-555555555555\", TransactionRuleUpdateRequest.builder()\n        .mode(TransactionRuleUpdateRequest.Mode.of(\"ACTIVE\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->rules->update('11111111-2222-3333-4444-555555555555', [\n    'mode' => 'ACTIVE',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.rules.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  mode: \"ACTIVE\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.Rules.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", new TransactionRuleUpdateRequest\n{\n    Mode = new TransactionRuleUpdateRequestMode(\"ACTIVE\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer la règle",
        "description": "Supprimer une règle CUSTOM. La suppression est immédiate et définitive : la règle cesse d'évaluer les nouvelles transactions et disparaît des listes, tandis que les exécutions passées de la règle sur les transactions déjà évaluées conservent leurs résultats enregistrés. Les règles de la bibliothèque ne peuvent pas être supprimées ; désinstallez-les plutôt via l'endpoint d'installation (elles peuvent toujours être réinstallées depuis la bibliothèque).",
        "operationId": "deleteTransactionRule",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Supprimé."
          },
          "400": {
            "description": "La règle est un préréglage de bibliothèque - désinstallez-le plutôt.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "detail": "Library rules cannot be deleted. Uninstall them via the rules install endpoint instead."
                }
              }
            }
          },
          "404": {
            "description": "Aucune règle de ce type sur cette application.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/transactions/rules/RULE_UUID/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.transactions.rules.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.transactions.rules.delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.Transactions.Rules.Delete(ctx, \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.transactions().rules().delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->transactions->rules->delete('11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.transactions.rules.delete(\"11111111-2222-3333-4444-555555555555\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.Transactions.Rules.DeleteAsync(\"11111111-2222-3333-4444-555555555555\");"
          }
        ]
      }
    },
    "/v3/transactions/rules/backtest/": {
      "post": {
        "summary": "Configuration de la règle de backtest",
        "description": "Évaluez une configuration de règle hypothétique par rapport à vos transactions récentes (les plus récentes en premier, jusqu'au plafond de test rétrospectif) sans créer de règle ni modifier de transaction. Utilisez-la avant d'activer une règle pour voir à quelle fréquence elle aurait été satisfaite et combien de sujets elle aurait affectés.",
        "operationId": "backtestTransactionRules",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "backtest",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionRuleBacktestRequest"
              },
              "example": {
                "conditions": [
                  {
                    "field": "currency",
                    "operator": "eq",
                    "value": "EUR"
                  },
                  {
                    "field": "amount",
                    "operator": "lt",
                    "value": 10000
                  }
                ],
                "aggregation": [
                  {
                    "metric": "count",
                    "operator": "gte",
                    "value": 20,
                    "window": "30d",
                    "filters": {
                      "direction": "INBOUND",
                      "transaction_type": "finance",
                      "subject_vendor_data": "__current__",
                      "currency": "EUR"
                    }
                  },
                  {
                    "metric": "max",
                    "field": "amount",
                    "operator": "lt",
                    "value": 10000,
                    "window": "30d",
                    "filters": {
                      "direction": "INBOUND",
                      "transaction_type": "finance",
                      "subject_vendor_data": "__current__",
                      "currency": "EUR"
                    }
                  }
                ],
                "evaluation_mode": "ALL",
                "scope": {
                  "transaction_types": [
                    "finance"
                  ],
                  "directions": [
                    "INBOUND"
                  ]
                },
                "period_days": 90
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Statistiques de backtest.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionRuleBacktestResult"
                },
                "example": {
                  "evaluated": 4820,
                  "matched": 12,
                  "affected_entities": 4,
                  "period_days": 90
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/transactions/rules/backtest/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"conditions\": [{\"field\": \"currency\", \"operator\": \"eq\", \"value\": \"EUR\"}, {\"field\": \"amount\", \"operator\": \"lt\", \"value\": 10000}], \"aggregation\": [{\"metric\": \"count\", \"operator\": \"gte\", \"value\": 20, \"window\": \"30d\", \"filters\": {\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"}}, {\"metric\": \"max\", \"field\": \"amount\", \"operator\": \"lt\", \"value\": 10000, \"window\": \"30d\", \"filters\": {\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"}}], \"evaluation_mode\": \"ALL\", \"scope\": {\"transaction_types\": [\"finance\"], \"directions\": [\"INBOUND\"]}, \"period_days\": 90}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.rules.backtest(\n    conditions=[{\n        \"field\": \"currency\",\n        \"operator\": \"eq\",\n        \"value\": \"EUR\",\n    }, {\n        \"field\": \"amount\",\n        \"operator\": \"lt\",\n        \"value\": 10000,\n    }],\n    aggregation=[{\n        \"metric\": \"count\",\n        \"operator\": \"gte\",\n        \"value\": 20.0,\n        \"window\": \"30d\",\n        \"filters\": {\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"},\n    }, {\n        \"metric\": \"max\",\n        \"field\": \"amount\",\n        \"operator\": \"lt\",\n        \"value\": 10000.0,\n        \"window\": \"30d\",\n        \"filters\": {\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"},\n    }],\n    evaluation_mode=\"ALL\",\n    scope={\n        \"transaction_types\": [\"finance\"],\n        \"directions\": [\"INBOUND\"],\n    },\n    period_days=90,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.rules.backtest({\n  conditions: [{\n    field: \"currency\",\n    operator: \"eq\",\n    value: \"EUR\",\n  }, {\n    field: \"amount\",\n    operator: \"lt\",\n    value: 10000,\n  }],\n  aggregation: [{\n    metric: \"count\",\n    operator: \"gte\",\n    value: 20.0,\n    window: \"30d\",\n    filters: { direction: \"INBOUND\", transaction_type: \"finance\", subject_vendor_data: \"__current__\", currency: \"EUR\" },\n  }, {\n    metric: \"max\",\n    field: \"amount\",\n    operator: \"lt\",\n    value: 10000.0,\n    window: \"30d\",\n    filters: { direction: \"INBOUND\", transaction_type: \"finance\", subject_vendor_data: \"__current__\", currency: \"EUR\" },\n  }],\n  evaluation_mode: \"ALL\",\n  scope: {\n    transaction_types: [\"finance\"],\n    directions: [\"INBOUND\"],\n  },\n  period_days: 90,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Rules.Backtest(ctx, didit.TransactionRuleBacktestRequest{\n\tConditions: didit.Some([]didit.TransactionRuleConditionParam{{\n\t\tField:    \"currency\",\n\t\tOperator: \"eq\",\n\t\tValue:    didit.Some[any](\"EUR\"),\n\t}, {\n\t\tField:    \"amount\",\n\t\tOperator: \"lt\",\n\t\tValue:    didit.Some[any](10000),\n\t}}),\n\tAggregation: didit.Some([]didit.TransactionRuleAggregationParam{{\n\t\tMetric:   didit.Some(didit.TransactionRuleAggregationMetric(\"count\")),\n\t\tOperator: didit.Some(didit.TransactionRuleAggregationOperator(\"gte\")),\n\t\tValue:    20.0,\n\t\tWindow:   didit.String(\"30d\"),\n\t\tFilters:  didit.Some(map[string]any{\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"}),\n\t}, {\n\t\tMetric:   didit.Some(didit.TransactionRuleAggregationMetric(\"max\")),\n\t\tField:    didit.String(\"amount\"),\n\t\tOperator: didit.Some(didit.TransactionRuleAggregationOperator(\"lt\")),\n\t\tValue:    10000.0,\n\t\tWindow:   didit.String(\"30d\"),\n\t\tFilters:  didit.Some(map[string]any{\"direction\": \"INBOUND\", \"transaction_type\": \"finance\", \"subject_vendor_data\": \"__current__\", \"currency\": \"EUR\"}),\n\t}}),\n\tEvaluationMode: didit.Some(didit.TransactionRuleBacktestRequestEvaluationMode(\"ALL\")),\n\tScope: didit.Some(didit.TransactionRuleScopeParam{\n\t\tTransactionTypes: didit.Some([]string{\"finance\"}),\n\t\tDirections:       didit.Some([]didit.TransactionRuleScopeDirections{\"INBOUND\"}),\n\t}),\n\tPeriodDays: didit.Int(90),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.TransactionRuleAggregation;\nimport me.didit.types.TransactionRuleBacktestRequest;\nimport me.didit.types.TransactionRuleCondition;\nimport me.didit.types.TransactionRuleScope;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().rules().backtest(TransactionRuleBacktestRequest.builder()\n        .conditions(List.of(\n                TransactionRuleCondition.builder()\n                        .field(\"currency\")\n                        .operator(TransactionRuleCondition.Operator.of(\"eq\"))\n                        .value(\"EUR\")\n                        .build(),\n                TransactionRuleCondition.builder()\n                        .field(\"amount\")\n                        .operator(TransactionRuleCondition.Operator.of(\"lt\"))\n                        .value(10000)\n                        .build()))\n        .aggregation(List.of(\n                TransactionRuleAggregation.builder()\n                        .metric(TransactionRuleAggregation.Metric.of(\"count\"))\n                        .operator(TransactionRuleAggregation.Operator.of(\"gte\"))\n                        .value(20.0)\n                        .window(\"30d\")\n                        .filters(Map.of(\"direction\", \"INBOUND\", \"transaction_type\", \"finance\", \"subject_vendor_data\", \"__current__\", \"currency\", \"EUR\"))\n                        .build(),\n                TransactionRuleAggregation.builder()\n                        .metric(TransactionRuleAggregation.Metric.of(\"max\"))\n                        .field(\"amount\")\n                        .operator(TransactionRuleAggregation.Operator.of(\"lt\"))\n                        .value(10000.0)\n                        .window(\"30d\")\n                        .filters(Map.of(\"direction\", \"INBOUND\", \"transaction_type\", \"finance\", \"subject_vendor_data\", \"__current__\", \"currency\", \"EUR\"))\n                        .build()))\n        .evaluationMode(TransactionRuleBacktestRequest.EvaluationMode.of(\"ALL\"))\n        .scope(TransactionRuleScope.builder()\n                .transactionTypes(List.of(\"finance\"))\n                .directions(List.of(TransactionRuleScope.Directions.of(\"INBOUND\")))\n                .build())\n        .periodDays(90L)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->rules->backtest([\n    'conditions' => [[\n        'field' => 'currency',\n        'operator' => 'eq',\n        'value' => 'EUR',\n    ], [\n        'field' => 'amount',\n        'operator' => 'lt',\n        'value' => 10000,\n    ]],\n    'aggregation' => [[\n        'metric' => 'count',\n        'operator' => 'gte',\n        'value' => 20.0,\n        'window' => '30d',\n        'filters' => ['direction' => 'INBOUND', 'transaction_type' => 'finance', 'subject_vendor_data' => '__current__', 'currency' => 'EUR'],\n    ], [\n        'metric' => 'max',\n        'field' => 'amount',\n        'operator' => 'lt',\n        'value' => 10000.0,\n        'window' => '30d',\n        'filters' => ['direction' => 'INBOUND', 'transaction_type' => 'finance', 'subject_vendor_data' => '__current__', 'currency' => 'EUR'],\n    ]],\n    'evaluation_mode' => 'ALL',\n    'scope' => [\n        'transaction_types' => ['finance'],\n        'directions' => ['INBOUND'],\n    ],\n    'period_days' => 90,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.rules.backtest(\n  conditions: [{\n    field: \"currency\",\n    operator: \"eq\",\n    value: \"EUR\",\n  }, {\n    field: \"amount\",\n    operator: \"lt\",\n    value: 10000,\n  }],\n  aggregation: [{\n    metric: \"count\",\n    operator: \"gte\",\n    value: 20.0,\n    window: \"30d\",\n    filters: { direction: \"INBOUND\", transaction_type: \"finance\", subject_vendor_data: \"__current__\", currency: \"EUR\" },\n  }, {\n    metric: \"max\",\n    field: \"amount\",\n    operator: \"lt\",\n    value: 10000.0,\n    window: \"30d\",\n    filters: { direction: \"INBOUND\", transaction_type: \"finance\", subject_vendor_data: \"__current__\", currency: \"EUR\" },\n  }],\n  evaluation_mode: \"ALL\",\n  scope: {\n    transaction_types: [\"finance\"],\n    directions: [\"INBOUND\"],\n  },\n  period_days: 90\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.Rules.BacktestAsync(new TransactionRuleBacktestRequest\n{\n    Conditions = new TransactionRuleCondition[]\n    {\n        new()\n        {\n            Field = \"currency\",\n            Operator = \"eq\",\n            Value = \"EUR\",\n        },\n        new()\n        {\n            Field = \"amount\",\n            Operator = \"lt\",\n            Value = 10000,\n        },\n    },\n    Aggregation = new TransactionRuleAggregation[]\n    {\n        new()\n        {\n            Metric = new TransactionRuleAggregationMetric(\"count\"),\n            Operator = new TransactionRuleAggregationOperator(\"gte\"),\n            Value = 20.0,\n            Window = \"30d\",\n            Filters = new Dictionary<string, object> { [\"direction\"] = \"INBOUND\", [\"transaction_type\"] = \"finance\", [\"subject_vendor_data\"] = \"__current__\", [\"currency\"] = \"EUR\" },\n        },\n        new()\n        {\n            Metric = new TransactionRuleAggregationMetric(\"max\"),\n            Field = \"amount\",\n            Operator = new TransactionRuleAggregationOperator(\"lt\"),\n            Value = 10000.0,\n            Window = \"30d\",\n            Filters = new Dictionary<string, object> { [\"direction\"] = \"INBOUND\", [\"transaction_type\"] = \"finance\", [\"subject_vendor_data\"] = \"__current__\", [\"currency\"] = \"EUR\" },\n        },\n    },\n    EvaluationMode = new TransactionRuleBacktestRequestEvaluationMode(\"ALL\"),\n    Scope = new TransactionRuleScope\n    {\n        TransactionTypes = new string[] { \"finance\" },\n        Directions = new TransactionRuleScopeDirections[] { \"INBOUND\" },\n    },\n    PeriodDays = 90,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/transactions/rules/library/": {
      "get": {
        "summary": "Lister la bibliothèque de règles",
        "description": "Parcourez la bibliothèque complète de règles prédéfinies (150+ règles) avec la configuration intégrale de chaque entrée et un indicateur `is_installed` pour cette application. Filtrez par pack, catégorie ou recherche en texte libre. Une règle de bibliothèque dont les conditions lisent des données que le moteur de règles ne peut pas encore évaluer est retenue jusqu'à ce qu'elle puisse s'exécuter. Les règles retenues ne sont pas listées.",
        "operationId": "listTransactionRuleLibrary",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "list_library",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "bundle",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filtrer par ensemble, par ex. finance, aml_ctf, crypto_monitoring, travel_rule"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filtrer par catégorie"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Correspondance insensible à la casse avec le titre et la description"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Taille de la page"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Décalage de page"
          }
        ],
        "responses": {
          "200": {
            "description": "Entrées de bibliothèque paginées.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TransactionRuleLibraryEntry"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/transactions/rules/library/?bundle=finance' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.transactions.rules.list_library():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.transactions.rules.listLibrary()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Transactions.Rules.ListLibraryAutoPaging(ctx, didit.TransactionsRulesListLibraryParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.transactions().rules().listLibrary()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->transactions->rules->listLibrary() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.transactions.rules.list_library.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Transactions.Rules.ListLibraryAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/transactions/rules/install/": {
      "post": {
        "summary": "Installer des règles de la bibliothèque",
        "description": "Installe un ou plusieurs préréglages sur l'application, par `library_keys` ou un `bundle` entier. Un préréglage installé est immédiatement actif lorsque la surveillance des transactions est activée, et désactivé dans le cas contraire ; les clés déjà installées sont ignorées. Une règle de bibliothèque dont les conditions lisent des données que le moteur de règles ne peut pas encore évaluer est mise en attente jusqu'à ce qu'elle puisse s'exécuter. Une requête mentionnant une règle dans `library_keys` renvoie une réponse 400 et n'installe rien (« Ces règles de bibliothèque ne peuvent pas encore s'exécuter : leurs conditions lisent des données que le moteur de règles ne peut pas évaluer. » suivi des clés), et une installation par `bundle` l'ignore. Une règle mise en attente redevient active d'elle-même dès que ses conditions peuvent être évaluées. Une entrée de `library_keys` qui ne figure pas dans la bibliothèque est ignorée, non refusée.",
        "operationId": "installTransactionRuleLibrary",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "install_library",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionRuleInstallRequest"
              },
              "example": {
                "library_keys": [
                  "structuring-inbound",
                  "structuring-outbound"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ce qui a été installé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionRuleInstallResult"
                },
                "example": {
                  "installed_library_keys": [
                    "structuring-inbound",
                    "structuring-outbound"
                  ],
                  "installed_count": 2
                }
              }
            }
          },
          "400": {
            "description": "Ni library_keys ni bundle n'ont été fournis, `library_keys` n'est pas une liste, ou une entrée de `library_keys` est retenue. Une entrée inconnue est ignorée et renvoie 200 sans elle.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/transactions/rules/install/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"library_keys\": [\"structuring-inbound\", \"structuring-outbound\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.rules.install_library(\n    library_keys=[\"structuring-inbound\", \"structuring-outbound\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.rules.installLibrary({\n  library_keys: [\"structuring-inbound\", \"structuring-outbound\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Rules.InstallLibrary(ctx, didit.TransactionRuleInstallRequest{\n\tLibraryKeys: didit.Some([]string{\"structuring-inbound\", \"structuring-outbound\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.TransactionRuleInstallRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().rules().installLibrary(TransactionRuleInstallRequest.builder()\n        .libraryKeys(List.of(\"structuring-inbound\", \"structuring-outbound\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->rules->installLibrary([\n    'library_keys' => ['structuring-inbound', 'structuring-outbound'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.rules.install_library(library_keys: [\"structuring-inbound\", \"structuring-outbound\"])\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.Rules.InstallLibraryAsync(new TransactionRuleInstallRequest\n{\n    LibraryKeys = new string[] { \"structuring-inbound\", \"structuring-outbound\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "summary": "Désinstaller les règles de la bibliothèque",
        "description": "Supprime les préréglages installés de l'application, par `library_keys` ou pour un `bundle` complet. Les préréglages désinstallés cessent immédiatement d'être évalués et peuvent être réinstallés depuis la bibliothèque à tout moment.",
        "operationId": "uninstallTransactionRuleLibrary",
        "x-didit-sdk": {
          "resource": "transactions.rules",
          "method": "uninstall_library",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionRuleInstallRequest"
              },
              "example": {
                "bundle": "responsible_gaming"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Nombre de préréglages supprimés.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionRuleInstallResult"
                },
                "example": {
                  "uninstalled_count": 5
                }
              }
            }
          },
          "400": {
            "description": "Ni library_keys ni bundle n'ont été fournis.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/transactions/rules/install/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"bundle\": \"responsible_gaming\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.rules.uninstall_library(\n    bundle=\"responsible_gaming\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.rules.uninstallLibrary({\n  bundle: \"responsible_gaming\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Rules.UninstallLibrary(ctx, didit.TransactionRuleInstallRequest{\n\tBundle: didit.String(\"responsible_gaming\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TransactionRuleInstallRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().rules().uninstallLibrary(TransactionRuleInstallRequest.builder()\n        .bundle(\"responsible_gaming\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->rules->uninstallLibrary([\n    'bundle' => 'responsible_gaming',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.rules.uninstall_library(bundle: \"responsible_gaming\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.Rules.UninstallLibraryAsync(new TransactionRuleInstallRequest\n{\n    Bundle = \"responsible_gaming\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/": {
      "get": {
        "summary": "Lister les réseaux",
        "description": "Lister les réseaux de fraude détectés au sein de l'organisation de cette application, par niveau de risque décroissant par défaut. Par défaut, les réseaux écartés sont exclus ; transmettez status pour les inclure. Les applications en sandbox n'ont jamais de réseaux : le regroupement exclut totalement les données de sandbox. Chaque réponse contient le `sharing_mode` de l'organisation et indique si les signaux inter-organisations s'appliquent à celle-ci (`cross_org_available`, `cross_org_unavailable_reason`). `kpis` agrège les réseaux correspondant à vos filtres et `counts` agrège tous les réseaux visibles par l'application ; passez `summary=false` pour ignorer les deux lorsque vous n'avez besoin que de la page. Nécessite une clé API avec accès complet, ou l'autorisation `list:networks` pour un membre de la console.",
        "operationId": "list_networks",
        "x-didit-sdk": {
          "resource": "networks",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Statuts à inclure séparés par des virgules : active,in_review,resolved,dismissed. Omettez pour exclure dismissed."
          },
          {
            "name": "scope",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "identity",
                "transactions"
              ]
            },
            "description": "`transactions` conserve les réseaux dont les membres sont tous des parties à la transaction ; `identity` conserve tous les autres réseaux. Omettez pour conserver les deux. Cela restreint également `counts.views` et `counts.facets`. Toute autre valeur renvoie 400."
          },
          {
            "name": "signal_type",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Types de signaux séparés par des virgules : ip_address,device,face,document_number,phone,email,address."
          },
          {
            "name": "pattern_type",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Types de motifs séparés par des virgules, par exemple exact_same_device,same_email."
          },
          {
            "name": "risk_band",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Paliers séparés par des virgules : low,medium,high."
          },
          {
            "name": "min_size",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Nombre minimum de membres."
          },
          {
            "name": "max_size",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Nombre maximal de membres."
          },
          {
            "name": "assignee",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Assignés séparés par des virgules : `unassigned`, adresses e-mail des membres (sans distinction majuscules/minuscules), ou `me` pour le membre appelant de la console. Un réseau correspond à n'importe quelle valeur. `me` requiert un token de membre de la console : une clé API renvoie l'erreur 400 `{\"assignee\": [\"\\\"me\\\" needs a user token; an API key has no assignee identity.\"]}`."
          },
          {
            "name": "priority",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Priorités séparées par des virgules : `low`, `medium`, `high`, ou `none` pour les réseaux sans priorité. Toute autre valeur renvoie 400 `{\"priority\": \"Unknown priority: <values>.\"}`."
          },
          {
            "name": "risk_min",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            },
            "description": "Score de risque minimum, un nombre entier de 0 à 100. Une valeur qui n'est pas un nombre entier renvoie 400 `{\"risk_min\": \"Use a whole number from 0 to 100.\"}`."
          },
          {
            "name": "has_case",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "`true` conserve les réseaux pour lesquels votre application a ouvert un dossier, `false` les autres. Toute autre valeur est ignorée."
          },
          {
            "name": "date_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Limite inférieure de last_activity_at (date ou horodatage ISO 8601)."
          },
          {
            "name": "date_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Limite supérieure pour first_activity_at (date ou date-heure ISO 8601)."
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Recherche en texte libre sur le nom du réseau, les noms des membres, le network_id (N-0001) et les tokens exacts de pattern_type."
          },
          {
            "name": "ordering",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "L'un des éléments suivants : risk_score, -risk_score, last_activity_at, -last_activity_at, first_activity_at, -first_activity_at, network_number, -network_number. Valeur par défaut : -risk_score,-last_activity_at."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100,
              "minimum": 1,
              "maximum": 500
            },
            "description": "Taille de page, de 1 à 500. Vaut 100 par défaut."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            },
            "description": "Décalage de départ (base zéro) du premier enregistrement."
          },
          {
            "name": "summary",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            },
            "description": "`false` renvoie uniquement la page et son `count`, sans `kpis` ni `counts`. La valeur par défaut est `true`. Toute valeur autre que `true` ou `false` renvoie 400."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/?status=active,in_review&ordering=-risk_score' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.networks.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.networks.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Networks.ListAutoPaging(ctx, didit.NetworksListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.networks().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->networks->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.networks.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Networks.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginée des réseaux, avec le mode de partage de l'organisation et la disponibilité inter-organisations, ainsi que les `kpis` et les `counts` sauf si `summary=false`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Offset de la page suivante, ou null sur la dernière page."
                    },
                    "previous": {
                      "type": "integer",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NetworkListItem"
                      }
                    },
                    "kpis": {
                      "type": "object",
                      "description": "Chaque clé est {value, delta} sur les résultats correspondant aux filtres actuels. Omise lorsque `summary=false`.",
                      "properties": {
                        "active": {
                          "type": "object"
                        },
                        "in_review": {
                          "type": "object"
                        },
                        "applicants_involved": {
                          "type": "object"
                        },
                        "detected_this_period": {
                          "type": "object"
                        },
                        "false_positive_rate": {
                          "type": "object"
                        }
                      }
                    },
                    "counts": {
                      "$ref": "#/components/schemas/NetworkListCounts"
                    },
                    "sharing_mode": {
                      "type": "string",
                      "enum": [
                        "off",
                        "private",
                        "global"
                      ],
                      "description": "Le mode de partage inter-organisations de l'organisation. Seul `global` compare les réseaux entre organisations ; `private` et `off` les conservent dans l'historique propre à l'organisation.",
                      "example": "global"
                    },
                    "cross_org_available": {
                      "type": "boolean",
                      "description": "Indique si les signaux inter-organisations s'appliquent à cette organisation. Ils nécessitent à la fois le forfait Enterprise et le mode de partage `global`.",
                      "example": true
                    },
                    "cross_org_unavailable_reason": {
                      "type": "string",
                      "enum": [
                        "plan",
                        "sharing_mode"
                      ],
                      "nullable": true,
                      "description": "Raison pour laquelle les signaux inter-organisations ne s'appliquent pas, vérifiée dans cet ordre. `plan` : le forfait de l'organisation n'inclut pas le réseau de fraude inter-organisations (le forfait Enterprise est requis), quel que soit le mode de partage. `sharing_mode` : le forfait l'inclut, mais le mode de partage est `private` ou `off`. Null lorsque `cross_org_available` est `true`.",
                      "example": null
                    }
                  },
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results",
                    "sharing_mode",
                    "cross_org_available",
                    "cross_org_unavailable_reason"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Une valeur non valide de filtre, de tri, de pagination ou de `summary`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid summary": {
                    "summary": "Résumé non valide",
                    "value": {
                      "summary": [
                        "Must be \"true\" or \"false\"."
                      ]
                    }
                  },
                  "Invalid scope": {
                    "summary": "Portée non valide",
                    "value": {
                      "scope": [
                        "Use identity or transactions."
                      ]
                    }
                  },
                  "Unsupported ordering": {
                    "summary": "Ordre de tri non pris en charge",
                    "value": [
                      "Unsupported ordering."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "Identifiants manquants ou invalides.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Identifiants manquants ou invalides",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé API appartient à une autre application, ou il s'agit d'une clé avec un accès restreint : les endpoints Networks nécessitent une clé avec accès complet. Un token de membre de la console nécessite `list:networks`. Renvoyé également avec `code: networks_not_entitled` lorsque Networks n'est pas activé pour l'organisation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Networks not enabled": {
                    "summary": "Réseaux non activés",
                    "value": {
                      "detail": "Networks is disabled for this organization. Contact Didit support if you believe this is an error.",
                      "code": "networks_not_entitled"
                    }
                  },
                  "Restricted API key": {
                    "summary": "Clé API restreinte",
                    "value": {
                      "detail": "This API key has no access to this endpoint."
                    }
                  },
                  "No permission": {
                    "summary": "Aucune autorisation",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/": {
      "get": {
        "summary": "Obtenir le réseau",
        "description": "Récupérer le détail complet d'un réseau unique : statistiques, tags de fraude et signaux de risque, ainsi que le `sharing_mode` de l'organisation et la disponibilité inter-organisations, les `tags` de votre application sur le réseau, les `outcomes` des membres et les scores de motifs (`patterns`). Nécessite une clé API à accès complet, ou `read:networks` pour un membre de la console.",
        "operationId": "get_network",
        "x-didit-sdk": {
          "resource": "networks",
          "method": "retrieve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "n3a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du réseau."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/n3a5e000-0000-4000-8000-000000000001/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.networks.retrieve(\n    \"n3a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.networks.retrieve(\"n3a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Networks.Retrieve(ctx, \"n3a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.networks().retrieve(\"n3a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->networks->retrieve('n3a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.networks.retrieve(\"n3a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.RetrieveAsync(\"n3a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Détail du réseau.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkDetailResponse"
                },
                "example": {
                  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "network_id": "N-0042",
                  "name": null,
                  "status": "in_review",
                  "risk": {
                    "score": 82,
                    "band": "high",
                    "bar": 0.82
                  },
                  "pattern_types": [
                    "exact_same_device",
                    "same_email"
                  ],
                  "signal_types": [
                    "device",
                    "email"
                  ],
                  "member_counts": {
                    "total": 3,
                    "users": 3,
                    "businesses": 0,
                    "transaction_parties": 0
                  },
                  "member_status": {
                    "approved": 1,
                    "declined": 1,
                    "in_review": 0,
                    "not_completed": 1
                  },
                  "signal_coverage": {
                    "device": {
                      "signals": 1,
                      "subjects": 3,
                      "coverage": 1.0
                    },
                    "email": {
                      "signals": 1,
                      "subjects": 2,
                      "coverage": 0.6667
                    }
                  },
                  "first_activity_at": "2026-10-01T09:12:44Z",
                  "last_activity_at": "2026-10-12T16:03:10Z",
                  "stats": {
                    "members": {
                      "total": 3,
                      "users": 3,
                      "businesses": 0,
                      "transaction_parties": 0
                    },
                    "member_status": {
                      "approved": 1,
                      "declined": 1,
                      "in_review": 0,
                      "not_completed": 1
                    },
                    "signals": {
                      "total": 2,
                      "by_type": {
                        "device": {
                          "signals": 1,
                          "subjects": 3,
                          "coverage": 1.0
                        },
                        "email": {
                          "signals": 1,
                          "subjects": 2,
                          "coverage": 0.6667
                        }
                      }
                    }
                  },
                  "fraud_tags": [],
                  "risk_signals": {
                    "residential_proxy_reuse": {
                      "detected": false,
                      "signal_count": 0,
                      "max_subject_count": 0
                    },
                    "email_intelligence": {
                      "enriched_signal_count": 1,
                      "high_risk_count": 0,
                      "social_profile_count": 0
                    },
                    "phone_intelligence": {
                      "enriched_signal_count": 0,
                      "high_risk_count": 0
                    }
                  },
                  "reviewed_at": "2026-10-12T16:30:00Z",
                  "reviewed_by": "reviewer@example.com",
                  "review_reason": "Shared device across three new accounts.",
                  "notes_count": 0,
                  "sharing_mode": "global",
                  "cross_org_available": true,
                  "cross_org_unavailable_reason": null,
                  "tags": [
                    {
                      "uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
                      "name": "SUSPICIOUS",
                      "color": "#6366F1",
                      "source": "custom",
                      "added_by": null,
                      "added_at": "2026-10-13T08:15:00Z"
                    }
                  ],
                  "outcomes": {
                    "approved": 1,
                    "declined": 1,
                    "in_review": 0,
                    "total": 3
                  },
                  "patterns": [
                    {
                      "type": "background",
                      "score": 0.8125,
                      "members": 3,
                      "reason": null,
                      "computed_at": "2026-10-13T08:00:00Z"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Réseau non trouvé (ou non visible pour cette application).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Identifiants manquants ou invalides.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Identifiants manquants ou invalides",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé API appartient à une autre application, ou il s'agit d'une clé avec un accès restreint : les endpoints Networks nécessitent une clé avec accès complet. Un token de membre de la console nécessite `read:networks`. Renvoyé également avec `code: networks_not_entitled` lorsque Networks n'est pas activé pour l'organisation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Networks not enabled": {
                    "summary": "Réseaux non activés",
                    "value": {
                      "detail": "Networks is disabled for this organization. Contact Didit support if you believe this is an error.",
                      "code": "networks_not_entitled"
                    }
                  },
                  "Restricted API key": {
                    "summary": "Clé API restreinte",
                    "value": {
                      "detail": "This API key has no access to this endpoint."
                    }
                  },
                  "No permission": {
                    "summary": "Aucune autorisation",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/graph/": {
      "get": {
        "summary": "Obtenir le graphe du réseau",
        "description": "Récupérer le réseau sous forme de graphe composé de nœuds représentant les sujets (utilisateurs du fournisseur, entreprises du fournisseur, parties à la transaction) et de nœuds de signaux (les valeurs partagées d'appareil/IP/visage/document/téléphone/e-mail/adresse qui les relient), avec des arêtes représentant les appartenances.",
        "operationId": "get_network_graph",
        "x-didit-sdk": {
          "resource": "networks",
          "method": "retrieve_graph",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "n3a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du réseau."
          },
          {
            "name": "depth",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "2",
                "3",
                "all"
              ]
            },
            "description": "Sauts à inclure à partir du sujet ciblé. Par défaut, tous (non limité)."
          },
          {
            "name": "focus_kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "vendor_user",
                "vendor_business",
                "transaction_party"
              ]
            },
            "description": "Type de sujet sur lequel centrer le graphe. Doit être fourni conjointement avec focus_id ; correspond par défaut à un membre arbitraire lorsque la profondeur est limitée et qu'aucun des deux n'est fourni."
          },
          {
            "name": "focus_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du sujet sur lequel centrer le graphe."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/n3a5e000-0000-4000-8000-000000000001/graph/?depth=2' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.networks.retrieve_graph(\n    \"n3a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.networks.retrieveGraph(\"n3a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Networks.RetrieveGraph(ctx, \"n3a5e000-0000-4000-8000-000000000001\", didit.NetworksRetrieveGraphParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.networks().retrieveGraph(\"n3a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->networks->retrieveGraph('n3a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.networks.retrieve_graph(\"n3a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.RetrieveGraphAsync(\"n3a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Graphe de réseau.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkGraph"
                }
              }
            }
          },
          "404": {
            "description": "Réseau non trouvé (ou non visible pour cette application).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/members/": {
      "get": {
        "summary": "Lister les membres du réseau",
        "description": "Lister les sujets (utilisateurs du fournisseur, entreprises du fournisseur ou parties à la transaction) qui appartiennent à ce réseau.",
        "operationId": "list_network_members",
        "x-didit-sdk": {
          "resource": "networks",
          "method": "list_members",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "n3a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du réseau."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/n3a5e000-0000-4000-8000-000000000001/members/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.networks.list_members(\n    \"n3a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.networks.listMembers(\"n3a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Networks.ListMembers(ctx, \"n3a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.networks().listMembers(\"n3a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->networks->listMembers('n3a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.networks.list_members(\"n3a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.ListMembersAsync(\"n3a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Membres du réseau. Non paginé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NetworkMember"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Réseau non trouvé (ou non visible pour cette application).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/signals/": {
      "get": {
        "summary": "Lister les signaux du réseau",
        "description": "Lister les signaux (appareil, IP, visage, numéro de document, téléphone, e-mail ou valeurs d'adresse partagés) qui relient les membres de ce réseau.",
        "operationId": "list_network_signals",
        "x-didit-sdk": {
          "resource": "networks",
          "method": "list_signals",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "n3a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du réseau."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/n3a5e000-0000-4000-8000-000000000001/signals/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.networks.list_signals(\n    \"n3a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.networks.listSignals(\"n3a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Networks.ListSignals(ctx, \"n3a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.networks().listSignals(\"n3a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->networks->listSignals('n3a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.networks.list_signals(\"n3a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.ListSignalsAsync(\"n3a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Signaux du réseau. Non paginé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NetworkSignal"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Réseau non trouvé (ou non visible pour cette application).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/timeline/": {
      "get": {
        "summary": "Obtenir la chronologie du réseau",
        "description": "Sans `contract` : les événements propres au réseau (détection, dernière observation de chaque signal et son examen), du plus ancien au plus récent et non paginés. `limit`, `cursor` et `event_type` sont ignorés. Avec `contract=2` : la chronologie typée, de la plus récente à la plus ancienne et paginée par curseur. Elle ajoute les actions effectuées par les comptes membres (tentatives de vérification, transactions, connexions que vous envoyez via l'API d'événements et les règles en direct qu'ils ont déclenchées) ainsi que les dossiers ouverts pour le réseau. Les événements `note_added` ne sont renvoyés qu'aux membres de la console, jamais à une clé API. Nécessite une clé API à accès complet, ou `read:networks` pour un membre de la console.",
        "operationId": "get_network_timeline",
        "x-didit-sdk": {
          "resource": "networks",
          "method": "retrieve_timeline",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "n3a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du réseau."
          },
          {
            "name": "contract",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "2"
              ]
            },
            "description": "`2` renvoie la chronologie typée. Omettez-le pour la chronologie par défaut. Toute autre valeur renvoie 400."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": "Uniquement pour une chronologie typée. Événements par page, de 1 à 500. Valeur par défaut : 100."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Uniquement pour une chronologie typée. Le `next_cursor` de la page précédente. Un curseur invalide ou vide renvoie 400."
          },
          {
            "name": "event_type",
            "in": "query",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "maxItems": 20,
              "items": {
                "type": "string",
                "enum": [
                  "network_detected",
                  "signal_observed",
                  "network_active",
                  "network_in_review",
                  "network_resolved",
                  "network_dismissed",
                  "verification_attempt",
                  "transaction",
                  "login",
                  "rule_hit",
                  "case_linked",
                  "note_added"
                ]
              }
            },
            "description": "Uniquement pour une chronologie typée. Types d'événements à conserver, répétés ou séparés par des virgules, au maximum 20 valeurs. Par défaut, tous les types."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/n3a5e000-0000-4000-8000-000000000001/timeline/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "curl",
            "label": "curl (typed timeline)",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/3fa85f64-5717-4562-b3fc-2c963f66afa6/timeline/?contract=2&limit=50&event_type=verification_attempt,login' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.networks.retrieve_timeline(\n    \"n3a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.networks.retrieveTimeline(\"n3a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Networks.RetrieveTimeline(ctx, \"n3a5e000-0000-4000-8000-000000000001\", didit.NetworksRetrieveTimelineParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.networks().retrieveTimeline(\"n3a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->networks->retrieveTimeline('n3a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.networks.retrieve_timeline(\"n3a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.RetrieveTimelineAsync(\"n3a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Sans `contract` : `{results}`, les plus anciens d'abord, non paginé. Avec `contract=2` : `{results, next_cursor}`, les plus récents d'abord.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/NetworkTimeline"
                    },
                    {
                      "$ref": "#/components/schemas/NetworkTimelinePage"
                    }
                  ]
                },
                "examples": {
                  "Default timeline": {
                    "summary": "Sans contrat",
                    "value": {
                      "results": [
                        {
                          "event_type": "network_detected",
                          "occurred_at": "2026-10-01T09:12:44Z",
                          "label": "Network detected",
                          "metadata": {
                            "network_id": "N-0042"
                          }
                        },
                        {
                          "event_type": "signal_observed",
                          "occurred_at": "2026-10-12T16:03:10Z",
                          "label": "device observed",
                          "metadata": {
                            "signal_type": "device",
                            "subject_count": 3,
                            "is_hub": false
                          }
                        },
                        {
                          "event_type": "network_in_review",
                          "occurred_at": "2026-10-12T16:30:00Z",
                          "label": "Network in_review",
                          "metadata": {
                            "reason": "Shared device across three new accounts."
                          }
                        }
                      ]
                    }
                  },
                  "Typed timeline": {
                    "summary": "Avec contract=2",
                    "value": {
                      "results": [
                        {
                          "id": "monitoring_event:9b2f1c3e-4d5a-4b6c-8d7e-0f1a2b3c4d5e",
                          "event_type": "login",
                          "occurred_at": "2026-10-12T18:41:02Z",
                          "ingested_at": "2026-10-12T18:41:03Z",
                          "label": "Login",
                          "metadata": {},
                          "account": {
                            "node_id": "vendor_user:5f6e7d8c-9b0a-4c1d-8e2f-3a4b5c6d7e8f",
                            "node_type": "account",
                            "uuid": "5f6e7d8c-9b0a-4c1d-8e2f-3a4b5c6d7e8f",
                            "vendor_data": "user-1042",
                            "display_name": "Alex Example",
                            "ownership": "owned",
                            "route": {
                              "kind": "user",
                              "id": "5f6e7d8c-9b0a-4c1d-8e2f-3a4b5c6d7e8f",
                              "application_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
                            }
                          },
                          "source_ref": {
                            "kind": "monitoring_event",
                            "id": "9b2f1c3e-4d5a-4b6c-8d7e-0f1a2b3c4d5e",
                            "ownership": "owned"
                          },
                          "verification_attempt": null,
                          "transaction": null,
                          "login": {
                            "action": "auth.login",
                            "succeeded": true,
                            "status": "APPROVED",
                            "ip": {
                              "address": "203.0.113.24",
                              "country_code": "ES",
                              "city": "Madrid",
                              "connection_type": null,
                              "is_vpn_or_tor": false,
                              "is_data_center": false
                            },
                            "device": {
                              "fingerprint": "fp_0a1b2c3d",
                              "label": "Chrome · Android"
                            },
                            "is_first_login": false,
                            "is_new_device": true
                          },
                          "rule_hit": null,
                          "case_linked": null,
                          "note_added": null
                        },
                        {
                          "id": "session:1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
                          "event_type": "verification_attempt",
                          "occurred_at": "2026-10-12T16:03:10Z",
                          "ingested_at": "2026-10-12T16:03:10Z",
                          "label": "Verification attempt 2 of 2",
                          "metadata": {},
                          "account": {
                            "node_id": "vendor_user:5f6e7d8c-9b0a-4c1d-8e2f-3a4b5c6d7e8f",
                            "node_type": "account",
                            "uuid": "5f6e7d8c-9b0a-4c1d-8e2f-3a4b5c6d7e8f",
                            "vendor_data": "user-1042",
                            "display_name": "Alex Example",
                            "ownership": "owned",
                            "route": {
                              "kind": "user",
                              "id": "5f6e7d8c-9b0a-4c1d-8e2f-3a4b5c6d7e8f",
                              "application_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
                            }
                          },
                          "source_ref": {
                            "kind": "session",
                            "id": "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
                            "ownership": "owned",
                            "route": {
                              "kind": "session",
                              "id": "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
                              "application_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
                            }
                          },
                          "verification_attempt": {
                            "session_id": "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
                            "session_number": 1287,
                            "attempt": 2,
                            "attempt_count": 2,
                            "status": "Approved",
                            "status_changed_at": "2026-10-12T16:05:41Z",
                            "decline_reasons": []
                          },
                          "transaction": null,
                          "login": null,
                          "rule_hit": null,
                          "case_linked": null,
                          "note_added": null
                        },
                        {
                          "id": "signal_observed:8d7c6b5a-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
                          "event_type": "signal_observed",
                          "occurred_at": "2026-10-12T16:03:10Z",
                          "ingested_at": "2026-10-01T09:12:44Z",
                          "label": "device observed",
                          "metadata": {
                            "signal_type": "device",
                            "subject_count": 3,
                            "is_hub": false
                          },
                          "account": null,
                          "source_ref": null,
                          "verification_attempt": null,
                          "transaction": null,
                          "login": null,
                          "rule_hit": null,
                          "case_linked": null,
                          "note_added": null
                        }
                      ],
                      "next_cursor": "eyJ0IjoiMjAyNi0xMC0xMlQxNjowMzoxMCswMDowMCIsImMiOiIyMDI2LTEwLTAxVDA5OjEyOjQ0KzAwOjAwIiwiciI6MSwidSI6IjhkN2M2YjVhLTRlM2YtNGEyYi05YzFkLTBlOWY4YTdiNmM1ZCJ9"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Avec `contract` présent : une valeur `contract`, `limit`, `cursor` ou `event_type` non valide.",
            "content": {
              "application/json": {
                "examples": {
                  "Unsupported contract": {
                    "summary": "Contrat non pris en charge",
                    "value": {
                      "contract": [
                        "\"3\" is not a valid choice."
                      ]
                    }
                  },
                  "Invalid cursor": {
                    "summary": "Curseur non valide",
                    "value": {
                      "cursor": [
                        "This cursor is not valid. Reload the feed."
                      ]
                    }
                  },
                  "Limit too large": {
                    "summary": "Limite trop grande",
                    "value": {
                      "limit": [
                        "Ensure this value is less than or equal to 500."
                      ]
                    }
                  },
                  "Unknown event type": {
                    "summary": "Type d'événement inconnu",
                    "value": {
                      "event_type": {
                        "0": [
                          "\"logout\" is not a valid choice."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Identifiants manquants ou invalides.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Identifiants manquants ou invalides",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé API appartient à une autre application, ou il s'agit d'une clé avec un accès restreint : les endpoints Networks nécessitent une clé avec accès complet. Un token de membre de la console nécessite `read:networks`. Renvoyé également avec `code: networks_not_entitled` lorsque Networks n'est pas activé pour l'organisation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Networks not enabled": {
                    "summary": "Réseaux non activés",
                    "value": {
                      "detail": "Networks is disabled for this organization. Contact Didit support if you believe this is an error.",
                      "code": "networks_not_entitled"
                    }
                  },
                  "Restricted API key": {
                    "summary": "Clé API restreinte",
                    "value": {
                      "detail": "This API key has no access to this endpoint."
                    }
                  },
                  "No permission": {
                    "summary": "Aucune autorisation",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Réseau non trouvé (ou non visible pour cette application).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/map/": {
      "get": {
        "summary": "Obtenir la carte du réseau",
        "description": "Points géographiques où convergent les adresses/localisations des membres de ce réseau, issus des sessions, des sessions d'entreprise et des transactions associées à ses adhésions.",
        "operationId": "get_network_map",
        "x-didit-sdk": {
          "resource": "networks",
          "method": "retrieve_map",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "n3a5e000-0000-4000-8000-000000000001"
            },
            "description": "UUID du réseau."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/n3a5e000-0000-4000-8000-000000000001/map/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.networks.retrieve_map(\n    \"n3a5e000-0000-4000-8000-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.networks.retrieveMap(\"n3a5e000-0000-4000-8000-000000000001\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Networks.RetrieveMap(ctx, \"n3a5e000-0000-4000-8000-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.networks().retrieveMap(\"n3a5e000-0000-4000-8000-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->networks->retrieveMap('n3a5e000-0000-4000-8000-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.networks.retrieve_map(\"n3a5e000-0000-4000-8000-000000000001\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.RetrieveMapAsync(\"n3a5e000-0000-4000-8000-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Carte du réseau.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkMap"
                }
              }
            }
          },
          "404": {
            "description": "Réseau non trouvé (ou non visible pour cette application).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/sessions/{session_id}/networks/": {
      "get": {
        "summary": "Lister les réseaux pour une session",
        "description": "Lister les réseaux auxquels appartient l'utilisateur du fournisseur de la session. Résolu via l'utilisateur lié aux vendor_data de la session.",
        "operationId": "list_session_network_memberships",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "list_networks",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de session."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/sessions/aaaaaaaa-0000-4000-8000-000000000001/networks/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.sessions.list_networks(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.sessions.listNetworks(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.ListNetworks(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.sessions().listNetworks(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->sessions->listNetworks('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.sessions.list_networks(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.ListNetworksAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Réseaux auxquels appartient cette entité. Non paginé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EntityNetworkMembershipList"
                }
              }
            }
          },
          "404": {
            "description": "Entité introuvable dans cette application, ou n'ayant aucun sujet associé à consulter.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/business-sessions/{business_session_id}/networks/": {
      "get": {
        "summary": "Lister les réseaux pour une session d'entreprise",
        "description": "Lister les réseaux auxquels appartient l'entreprise du fournisseur de la session d'entreprise.",
        "operationId": "list_business_session_network_memberships",
        "x-didit-sdk": {
          "resource": "business_sessions",
          "method": "list_networks",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "business_session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de session entreprise."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/business-sessions/aaaaaaaa-0000-4000-8000-000000000002/networks/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.business_sessions.list_networks(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.businessSessions.listNetworks(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.BusinessSessions.ListNetworks(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.businessSessions().listNetworks(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->businessSessions->listNetworks('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.business_sessions.list_networks(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.BusinessSessions.ListNetworksAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Réseaux auxquels appartient cette entité. Non paginé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EntityNetworkMembershipList"
                }
              }
            }
          },
          "404": {
            "description": "Entité introuvable dans cette application, ou n'ayant aucun sujet associé à consulter.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/users/{vendor_user_uuid}/networks/": {
      "get": {
        "summary": "Lister les réseaux pour un utilisateur",
        "description": "Lister les réseaux auxquels appartient un utilisateur du fournisseur.",
        "operationId": "list_user_network_memberships",
        "x-didit-sdk": {
          "resource": "users",
          "method": "list_networks",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "vendor_user_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'utilisateur du fournisseur."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/users/aaaaaaaa-0000-4000-8000-000000000003/networks/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.users.list_networks(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.users.listNetworks(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Users.ListNetworks(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.users().listNetworks(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->users->listNetworks('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.users.list_networks(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Users.ListNetworksAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Réseaux auxquels appartient cette entité. Non paginé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EntityNetworkMembershipList"
                }
              }
            }
          },
          "404": {
            "description": "Entité introuvable dans cette application, ou n'ayant aucun sujet associé à consulter.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/businesses/{vendor_business_uuid}/networks/": {
      "get": {
        "summary": "Lister les réseaux pour une entreprise",
        "description": "Lister les réseaux auxquels appartient une entreprise du fournisseur.",
        "operationId": "list_business_network_memberships",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "list_networks",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "vendor_business_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'entreprise du fournisseur."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/businesses/aaaaaaaa-0000-4000-8000-000000000004/networks/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.businesses.list_networks(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.businesses.listNetworks(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Businesses.ListNetworks(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.businesses().listNetworks(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->businesses->listNetworks('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.businesses.list_networks(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Businesses.ListNetworksAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Réseaux auxquels appartient cette entité. Non paginé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EntityNetworkMembershipList"
                }
              }
            }
          },
          "404": {
            "description": "Entité introuvable dans cette application, ou n'ayant aucun sujet associé à consulter.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/transactions/{transaction_uuid}/networks/": {
      "get": {
        "summary": "Lister les réseaux pour une transaction",
        "description": "Lister les réseaux auxquels appartient le sujet KYC/KYB sous-jacent de la transaction (résolu via la session ou la session d'entreprise de la transaction).",
        "operationId": "list_transaction_network_memberships",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "list_networks",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "transaction_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de la transaction."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/transactions/aaaaaaaa-0000-4000-8000-000000000005/networks/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.transactions.list_networks(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.transactions.listNetworks(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.ListNetworks(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.transactions().listNetworks(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->transactions->listNetworks('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.transactions.list_networks(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.ListNetworksAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Réseaux auxquels appartient cette entité. Non paginé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EntityNetworkMembershipList"
                }
              }
            }
          },
          "404": {
            "description": "Entité introuvable dans cette application, ou n'ayant aucun sujet associé à consulter.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/transactions/{transaction_uuid}/parties/{transaction_party_uuid}/networks/": {
      "get": {
        "summary": "Lister les réseaux pour une partie de la transaction",
        "description": "Lister les réseaux auxquels appartient une partie de transaction (donneur d'ordre, bénéficiaire ou contrepartie), résolus via la partie elle-même plutôt que via la session sous-jacente de la transaction.",
        "operationId": "list_transaction_party_network_memberships",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "list_party_networks",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "transaction_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de la transaction."
          },
          {
            "name": "transaction_party_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de la partie à la transaction."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/transactions/aaaaaaaa-0000-4000-8000-000000000005/parties/bbbbbbbb-0000-4000-8000-000000000006/networks/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.transactions.list_party_networks(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.transactions.listPartyNetworks(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.ListPartyNetworks(ctx, \"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.transactions().listPartyNetworks(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->transactions->listPartyNetworks('11111111-2222-3333-4444-555555555555', '11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.transactions.list_party_networks(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.ListPartyNetworksAsync(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Réseaux auxquels appartient cette entité. Non paginé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EntityNetworkMembershipList"
                }
              }
            }
          },
          "404": {
            "description": "Entité introuvable dans cette application, ou n'ayant aucun sujet associé à consulter.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/biometric-templates/": {
      "get": {
        "summary": "Lister les gabarits biométriques conservés",
        "description": "Une application ayant activé cette option conserve un gabarit biométrique facial géré séparément et sans image, ancré à l'Utilisateur lorsqu'une session est supprimée (voir `DELETE /v3/session/{sessionId}/delete/`). Les gabarits sont des données biométriques avec un `expires_at` fini ; ils ne contiennent jamais d'images, de données de session ou de champs d'identité, et ils sont purgés lors de la suppression de l'Utilisateur, d'un effacement pour des raisons de confidentialité, de leur expiration ou d'une purge explicite. Ces endpoints acceptent uniquement les clés API d'application (`x-api-key`) ; les tokens d'utilisateur de la Business Console sont rejetés avec `403`.\n\nRenvoie une liste paginée des gabarits actuellement détenus par l'application. Les gabarits purgés ne sont pas listés.",
        "operationId": "list_biometric_templates",
        "x-didit-sdk": {
          "resource": "biometric_templates",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Biometric Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "vendor_data",
            "required": false,
            "description": "Correspondance insensible à la casse sur une sous-chaîne du `vendor_data` actuel de l'utilisateur propriétaire.",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "vendor_user_uuid",
            "required": false,
            "description": "Correspondance exacte sur l'utilisateur propriétaire.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "description": "Statut de cycle de vie. Les modèles purgés ne sont jamais listés.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "active",
                "expired",
                "held_out_of_use",
                "purge_pending",
                "purge_failed"
              ]
            }
          },
          {
            "in": "query",
            "name": "source_type",
            "required": false,
            "description": "Manière dont le modèle a été créé.",
            "schema": {
              "type": "string",
              "enum": [
                "session_delete",
                "automatic_retention",
                "backfill"
              ]
            }
          },
          {
            "in": "query",
            "name": "retained_from",
            "required": false,
            "description": "Modèles conservés à cette date ou après.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "retained_to",
            "required": false,
            "description": "Modèles conservés à cette date ou avant. Ne doit pas être antérieure à `retained_from` (`400`).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "ordering",
            "required": false,
            "description": "Ordre de tri.",
            "schema": {
              "type": "string",
              "enum": [
                "retained_at",
                "-retained_at",
                "expires_at",
                "-expires_at"
              ],
              "default": "-retained_at"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Taille de la page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "description": "Offset de pagination.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Modèles paginés.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Identifiant du modèle. Généré de manière aléatoire ; non dérivé de la session supprimée ou de son visage."
                          },
                          "vendor_user_uuid": {
                            "type": "string",
                            "format": "uuid",
                            "description": "L'utilisateur propriétaire."
                          },
                          "vendor_data": {
                            "type": "string",
                            "nullable": true,
                            "description": "Les `vendor_data` actuelles de l'utilisateur, résolues lorsque vous lisez le modèle (jamais copiées)."
                          },
                          "source_type": {
                            "type": "string",
                            "enum": [
                              "session_delete",
                              "automatic_retention",
                              "backfill"
                            ],
                            "description": "Manière dont le modèle a été créé : suppression d'une session (API ou Console), fenêtre automatique de conservation des données de l'application, ou rétro-remplissage opéré par Didit sur votre instruction."
                          },
                          "provenance_reference": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Référence opaque liant le modèle à son journal d'audit. Il ne s'agit pas de l'identifiant de la session supprimée et il ne peut pas être résolu vers celui-ci."
                          },
                          "retention_policy": {
                            "type": "string",
                            "enum": [
                              "delete_with_session",
                              "retain_until_user_deleted"
                            ],
                            "description": "La politique de l'application au moment de la conservation."
                          },
                          "retention_override": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "La valeur `retain_face_embeddings` envoyée lors de la suppression, ou `null` lorsque la politique s'est appliquée."
                          },
                          "retained_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "expires_at": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Moment où le modèle expire et est purgé automatiquement. Toujours défini."
                          },
                          "retained_by": {
                            "type": "string",
                            "nullable": true,
                            "description": "Entité principale ayant donné l'instruction : l'ID d'application pour les clés API, l'ID de membre de la Console pour les actions dans la Console, ou un identifiant `service:` pour la conservation automatique. Jamais une adresse e-mail."
                          },
                          "retained_by_type": {
                            "type": "string",
                            "enum": [
                              "API_KEY",
                              "CONSOLE_USER",
                              "SYSTEM"
                            ]
                          },
                          "instruction_class": {
                            "type": "string",
                            "enum": [
                              "operational_session_delete",
                              "privacy_erasure"
                            ]
                          },
                          "instruction_source": {
                            "type": "string",
                            "enum": [
                              "api",
                              "console",
                              "automatic_retention",
                              "backfill",
                              "privacy_erasure",
                              "explicit_template_purge",
                              "vendor_user_delete",
                              "expiry",
                              "reconciliation",
                              "migration",
                              "system"
                            ]
                          },
                          "instruction_id": {
                            "type": "string",
                            "description": "L'`instruction_id` envoyé lors de la suppression, ou un identifiant généré par Didit."
                          },
                          "held_out_of_use": {
                            "type": "boolean",
                            "description": "`true` uniquement lorsqu'une obligation légale de conservation (legal hold) s'applique. Un gabarit conservé est exclu de toute mise en correspondance."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "active",
                              "expired",
                              "held_out_of_use",
                              "purge_pending",
                              "purge_failed",
                              "purged"
                            ],
                            "description": "Seuls les modèles `active` qui ne sont pas suspendus, dont la date `expires_at` n'est pas dépassée et dont l'utilisateur existe toujours participent à la correspondance."
                          },
                          "purged_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "One active template": {
                    "value": {
                      "count": 1,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
                          "vendor_user_uuid": "2f7c1a9e-8b4d-4c6a-9e1f-3d5b7a9c1e2f",
                          "vendor_data": "user-42",
                          "source_type": "session_delete",
                          "provenance_reference": "6b1e8d2f-4a3c-4f9e-8c7d-1a2b3c4d5e6f",
                          "retention_policy": "retain_until_user_deleted",
                          "retention_override": null,
                          "retained_at": "2026-08-28T10:15:42.318402Z",
                          "expires_at": "2027-08-28T10:15:42.318402Z",
                          "retained_by": "3c9e2b1f-7d4a-4e8b-9c1d-5f6a7b8c9d0e",
                          "retained_by_type": "API_KEY",
                          "instruction_class": "operational_session_delete",
                          "instruction_source": "api",
                          "instruction_id": "post-approval-cleanup-2026-08",
                          "held_out_of_use": false,
                          "status": "active",
                          "purged_at": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Valeur de filtre non valide, ou `retained_to` antérieur à `retained_from`. Erreurs de validation indexées par champ.",
            "content": {
              "application/json": {
                "examples": {
                  "Bad range": {
                    "value": {
                      "retained_to": [
                        "Must be on or after retained_from."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Token de l'utilisateur de la Console, ou clé API non autorisée. Ces endpoints acceptent uniquement les clés API d'application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/biometric-templates/?vendor_data=user-42&status=active' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.biometric_templates.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.biometricTemplates.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.BiometricTemplates.ListAutoPaging(ctx, didit.BiometricTemplatesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.biometricTemplates().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->biometricTemplates->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.biometric_templates.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.BiometricTemplates.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/biometric-templates/count/": {
      "get": {
        "summary": "Compter les gabarits biométriques conservés",
        "description": "Une application ayant activé cette option conserve un gabarit biométrique facial géré séparément et sans image, ancré à l'Utilisateur lorsqu'une session est supprimée (voir `DELETE /v3/session/{sessionId}/delete/`). Les gabarits sont des données biométriques avec un `expires_at` fini ; ils ne contiennent jamais d'images, de données de session ou de champs d'identité, et ils sont purgés lors de la suppression de l'Utilisateur, d'un effacement pour des raisons de confidentialité, de leur expiration ou d'une purge explicite. Ces endpoints acceptent uniquement les clés API d'application (`x-api-key`) ; les tokens d'utilisateur de la Business Console sont rejetés avec `403`.\n\nRenvoie le nombre de gabarits correspondant aux mêmes filtres que l'endpoint de liste. Utilisez-le pour vérifier ce qu'une purge en masse filtrée avec `delete_all: true` affecterait.",
        "operationId": "count_biometric_templates",
        "x-didit-sdk": {
          "resource": "biometric_templates",
          "method": "count",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Biometric Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "vendor_data",
            "required": false,
            "description": "Correspondance insensible à la casse sur une sous-chaîne du `vendor_data` actuel de l'utilisateur propriétaire.",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "vendor_user_uuid",
            "required": false,
            "description": "Correspondance exacte sur l'utilisateur propriétaire.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "description": "Statut de cycle de vie. Les modèles purgés ne sont jamais listés.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "active",
                "expired",
                "held_out_of_use",
                "purge_pending",
                "purge_failed"
              ]
            }
          },
          {
            "in": "query",
            "name": "source_type",
            "required": false,
            "description": "Manière dont le modèle a été créé.",
            "schema": {
              "type": "string",
              "enum": [
                "session_delete",
                "automatic_retention",
                "backfill"
              ]
            }
          },
          {
            "in": "query",
            "name": "retained_from",
            "required": false,
            "description": "Modèles conservés à cette date ou après.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "retained_to",
            "required": false,
            "description": "Modèles conservés à cette date ou avant. Ne doit pas être antérieure à `retained_from` (`400`).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Nombre.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "minimum": 0
                    }
                  }
                },
                "examples": {
                  "Count": {
                    "value": {
                      "count": 128
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Valeur de filtre non valide, ou `retained_to` antérieur à `retained_from`. Erreurs de validation indexées par champ.",
            "content": {
              "application/json": {
                "examples": {
                  "Bad range": {
                    "value": {
                      "retained_to": [
                        "Must be on or after retained_from."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Token de l'utilisateur de la Console, ou clé API non autorisée. Ces endpoints acceptent uniquement les clés API d'application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/biometric-templates/count/?status=active' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.biometric_templates.count()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.biometricTemplates.count();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.BiometricTemplates.Count(ctx, didit.BiometricTemplatesCountParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.biometricTemplates().count();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->biometricTemplates->count();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.biometric_templates.count\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.BiometricTemplates.CountAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/biometric-templates/{template_uuid}/": {
      "get": {
        "summary": "Obtenir un gabarit biométrique conservé",
        "description": "Une application ayant activé cette option conserve un gabarit biométrique facial géré séparément et sans image, ancré à l'Utilisateur lorsqu'une session est supprimée (voir `DELETE /v3/session/{sessionId}/delete/`). Les gabarits sont des données biométriques avec un `expires_at` fini ; ils ne contiennent jamais d'images, de données de session ou de champs d'identité, et ils sont purgés lors de la suppression de l'Utilisateur, d'un effacement pour des raisons de confidentialité, de leur expiration ou d'une purge explicite. Ces endpoints acceptent uniquement les clés API d'application (`x-api-key`) ; les tokens d'utilisateur de la Business Console sont rejetés avec `403`.\n\nRenvoie un gabarit. La réponse n'inclut jamais d'image, de vecteur, d'identifiant de la session supprimée ou de données d'identité.",
        "operationId": "get_biometric_template",
        "x-didit-sdk": {
          "resource": "biometric_templates",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Biometric Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "template_uuid",
            "required": true,
            "description": "Identifiant du modèle, tel que renvoyé dans `biometric_template_uuid` par les endpoints de suppression de session, `biometric_template_id` lors d'une correspondance de Recherche faciale, ou l'endpoint de liste.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Le modèle.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant du modèle. Généré de manière aléatoire ; non dérivé de la session supprimée ou de son visage."
                    },
                    "vendor_user_uuid": {
                      "type": "string",
                      "format": "uuid",
                      "description": "L'utilisateur propriétaire."
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Les `vendor_data` actuelles de l'utilisateur, résolues lorsque vous lisez le modèle (jamais copiées)."
                    },
                    "source_type": {
                      "type": "string",
                      "enum": [
                        "session_delete",
                        "automatic_retention",
                        "backfill"
                      ],
                      "description": "Manière dont le modèle a été créé : suppression d'une session (API ou Console), fenêtre automatique de conservation des données de l'application, ou rétro-remplissage opéré par Didit sur votre instruction."
                    },
                    "provenance_reference": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Référence opaque liant le modèle à son journal d'audit. Il ne s'agit pas de l'identifiant de la session supprimée et il ne peut pas être résolu vers celui-ci."
                    },
                    "retention_policy": {
                      "type": "string",
                      "enum": [
                        "delete_with_session",
                        "retain_until_user_deleted"
                      ],
                      "description": "La politique de l'application au moment de la conservation."
                    },
                    "retention_override": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "La valeur `retain_face_embeddings` envoyée lors de la suppression, ou `null` lorsque la politique s'est appliquée."
                    },
                    "retained_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Moment où le modèle expire et est purgé automatiquement. Toujours défini."
                    },
                    "retained_by": {
                      "type": "string",
                      "nullable": true,
                      "description": "Entité principale ayant donné l'instruction : l'ID d'application pour les clés API, l'ID de membre de la Console pour les actions dans la Console, ou un identifiant `service:` pour la conservation automatique. Jamais une adresse e-mail."
                    },
                    "retained_by_type": {
                      "type": "string",
                      "enum": [
                        "API_KEY",
                        "CONSOLE_USER",
                        "SYSTEM"
                      ]
                    },
                    "instruction_class": {
                      "type": "string",
                      "enum": [
                        "operational_session_delete",
                        "privacy_erasure"
                      ]
                    },
                    "instruction_source": {
                      "type": "string",
                      "enum": [
                        "api",
                        "console",
                        "automatic_retention",
                        "backfill",
                        "privacy_erasure",
                        "explicit_template_purge",
                        "vendor_user_delete",
                        "expiry",
                        "reconciliation",
                        "migration",
                        "system"
                      ]
                    },
                    "instruction_id": {
                      "type": "string",
                      "description": "L'`instruction_id` envoyé lors de la suppression, ou un identifiant généré par Didit."
                    },
                    "held_out_of_use": {
                      "type": "boolean",
                      "description": "`true` uniquement lorsqu'une obligation légale de conservation (legal hold) s'applique. Un gabarit conservé est exclu de toute mise en correspondance."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "active",
                        "expired",
                        "held_out_of_use",
                        "purge_pending",
                        "purge_failed",
                        "purged"
                      ],
                      "description": "Seuls les modèles `active` qui ne sont pas suspendus, dont la date `expires_at` n'est pas dépassée et dont l'utilisateur existe toujours participent à la correspondance."
                    },
                    "purged_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    }
                  }
                },
                "examples": {
                  "Active template": {
                    "value": {
                      "uuid": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
                      "vendor_user_uuid": "2f7c1a9e-8b4d-4c6a-9e1f-3d5b7a9c1e2f",
                      "vendor_data": "user-42",
                      "source_type": "session_delete",
                      "provenance_reference": "6b1e8d2f-4a3c-4f9e-8c7d-1a2b3c4d5e6f",
                      "retention_policy": "retain_until_user_deleted",
                      "retention_override": null,
                      "retained_at": "2026-08-28T10:15:42.318402Z",
                      "expires_at": "2027-08-28T10:15:42.318402Z",
                      "retained_by": "3c9e2b1f-7d4a-4e8b-9c1d-5f6a7b8c9d0e",
                      "retained_by_type": "API_KEY",
                      "instruction_class": "operational_session_delete",
                      "instruction_source": "api",
                      "instruction_id": "post-approval-cleanup-2026-08",
                      "held_out_of_use": false,
                      "status": "active",
                      "purged_at": null
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Token de l'utilisateur de la Console, ou clé API non autorisée. Ces endpoints acceptent uniquement les clés API d'application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Modèle inconnu, modèle appartenant à une autre application, ou (sur `GET`) modèle purgé.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Biometric template not found."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/biometric-templates/9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.biometric_templates.retrieve(\n    \"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.biometricTemplates.retrieve(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.BiometricTemplates.Retrieve(ctx, \"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.biometricTemplates().retrieve(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->biometricTemplates->retrieve('9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.biometric_templates.retrieve(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.BiometricTemplates.RetrieveAsync(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "summary": "Purger un gabarit biométrique conservé",
        "description": "Une application ayant activé cette option conserve un gabarit biométrique facial géré séparément et sans image, ancré à l'Utilisateur lorsqu'une session est supprimée (voir `DELETE /v3/session/{sessionId}/delete/`). Les gabarits sont des données biométriques avec une valeur `expires_at` finie ; ils ne contiennent jamais d'images, de données de session ou de champs d'identité, et ils sont purgés lors de la suppression de l'Utilisateur, d'un effacement pour des raisons de confidentialité, de leur expiration ou d'une purge explicite. Ces endpoints acceptent uniquement les clés API d'application (`x-api-key`) ; les tokens d'utilisateur de la Business Console sont rejetés avec `403`.\n\nPurge un gabarit : il est retiré de tout type de correspondance et le gabarit stocké est supprimé. Irréversible et consigné dans le journal d'audit avec l'identité de l'auteur de l'action.\n\n**Sémantique des réessais :** Didit supprime d'abord le gabarit stocké et marque seulement ensuite le gabarit comme purgé. Si un magasin biométrique est indisponible, l'appel renvoie `503`, le gabarit passe à `status: purge_failed` et est déjà exclu des correspondances ; répétez le même appel pour terminer. Répéter la purge d'un gabarit déjà purgé renvoie `already_purged`.\n\nLes gabarits sont également purgés par `POST /v3/users/delete/` pour l'Utilisateur propriétaire, par toute suppression des sessions de cet Utilisateur avec `deletion_instruction: privacy_erasure`, et automatiquement à `expires_at`.",
        "operationId": "purge_biometric_template",
        "x-didit-sdk": {
          "resource": "biometric_templates",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Biometric Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "template_uuid",
            "required": true,
            "description": "Identifiant du modèle, tel que renvoyé dans `biometric_template_uuid` par les endpoints de suppression de session, `biometric_template_id` lors d'une correspondance de Recherche faciale, ou l'endpoint de liste.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat de la purge.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "outcome": {
                      "type": "string",
                      "enum": [
                        "purged",
                        "already_purged"
                      ]
                    }
                  }
                },
                "examples": {
                  "Purged": {
                    "value": {
                      "uuid": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
                      "outcome": "purged"
                    }
                  },
                  "Already purged": {
                    "value": {
                      "uuid": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
                      "outcome": "already_purged"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Token de l'utilisateur de la Console, ou clé API non autorisée. Ces endpoints acceptent uniquement les clés API d'application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Modèle inconnu, modèle appartenant à une autre application, ou (sur `GET`) modèle purgé.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Biometric template not found."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Un service de stockage biométrique était indisponible lors de la conservation ou de la suppression définitive d'un gabarit biométrique. Rien n'est supprimé ; réitérez la même requête. Les nouvelles tentatives sont idempotentes et convergent vers un seul gabarit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Retryable": {
                    "value": {
                      "detail": "The biometric-template operation could not finish because an external store is unavailable. The operation is retryable."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE https://verification.didit.me/v3/biometric-templates/9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.biometric_templates.delete(\n    \"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.biometricTemplates.delete(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.BiometricTemplates.Delete(ctx, \"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.biometricTemplates().delete(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->biometricTemplates->delete('9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.biometric_templates.delete(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.BiometricTemplates.DeleteAsync(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/biometric-templates/delete/": {
      "post": {
        "summary": "Purger en masse les gabarits biométriques conservés",
        "description": "Une application ayant activé l'option conserve un gabarit biométrique facial sans image, géré séparément et rattaché à l'utilisateur lorsqu'une session est supprimée (voir `DELETE /v3/session/{sessionId}/delete/`). Les gabarits sont des données biométriques avec un `expires_at` défini ; ils ne contiennent jamais d'images, de données de session ou de champs d'identité, et ils sont purgés lors de la suppression de l'utilisateur, de l'effacement au titre de la confidentialité, de l'expiration ou d'une purge explicite. Ces endpoints acceptent uniquement des clés API d'application (`x-api-key`) ; les tokens d'utilisateur de la Business Console sont rejetés avec `403`.\n\nPurge plusieurs gabarits en un seul appel, par une liste explicite d'identifiants ou avec `delete_all: true` éventuellement restreint par les mêmes filtres que l'endpoint de liste. Les gabarits sont purgés un par un et chaque résultat indique `purged` ou `already_purged`. Si un magasin biométrique est indisponible, l'appel renvoie `503` au premier gabarit en échec : les gabarits purgés plus tôt dans la requête restent purgés, celui en échec passe à `purge_failed` (déjà exclu des correspondances), et renouveler la requête permet de terminer l'opération.\n\n**`delete_all: true` sans filtre purge tous les gabarits biométriques de l'application et ne peut pas être annulé.** Exécutez d'abord l'endpoint de comptage avec les mêmes filtres.",
        "operationId": "bulk_purge_biometric_templates",
        "x-didit-sdk": {
          "resource": "biometric_templates",
          "method": "batch_delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Biometric Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "template_uuids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1,
                    "description": "Modèles à purger. Obligatoire sauf si `delete_all` est `true`. Les identifiants déjà purgés sont signalés comme `already_purged`."
                  },
                  "delete_all": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lorsque la valeur est `true`, purge chaque modèle correspondant aux filtres ci-dessous (tous les modèles de l'application si aucun filtre n'est fourni). `template_uuids` est ignoré. Irréversible."
                  },
                  "vendor_data": {
                    "type": "string",
                    "description": "Uniquement avec `delete_all` : correspondance de sous-chaîne insensible à la casse sur le `vendor_data` de l'utilisateur propriétaire."
                  },
                  "vendor_user_uuid": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Uniquement avec `delete_all` : correspondance exacte sur l'utilisateur propriétaire."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "pending",
                      "active",
                      "expired",
                      "held_out_of_use",
                      "purge_pending",
                      "purge_failed"
                    ],
                    "description": "Uniquement avec `delete_all`."
                  },
                  "source_type": {
                    "type": "string",
                    "enum": [
                      "session_delete",
                      "automatic_retention",
                      "backfill"
                    ],
                    "description": "Uniquement avec `delete_all`."
                  },
                  "retained_from": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Uniquement avec `delete_all`."
                  },
                  "retained_to": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Uniquement avec `delete_all`. Ne doit pas être antérieur à `retained_from`."
                  }
                }
              },
              "examples": {
                "By id": {
                  "value": {
                    "template_uuids": [
                      "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
                      "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                    ]
                  }
                },
                "Every template of one User": {
                  "value": {
                    "delete_all": true,
                    "vendor_user_uuid": "2f7c1a9e-8b4d-4c6a-9e1f-3d5b7a9c1e2f"
                  }
                },
                "Every template in the application": {
                  "value": {
                    "delete_all": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultats de purge par modèle.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "outcome": {
                            "type": "string",
                            "enum": [
                              "purged",
                              "already_purged"
                            ]
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Mixed": {
                    "value": {
                      "results": [
                        {
                          "uuid": "9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b",
                          "outcome": "purged"
                        },
                        {
                          "uuid": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                          "outcome": "already_purged"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation — rien n'est purgé.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing selector": {
                    "value": {
                      "template_uuids": [
                        "This field is required unless delete_all is true."
                      ]
                    }
                  },
                  "Bad range": {
                    "value": {
                      "retained_to": [
                        "Must be on or after retained_from."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Token de l'utilisateur de la Console, ou clé API non autorisée. Ces endpoints acceptent uniquement les clés API d'application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Un service de stockage biométrique était indisponible lors de la conservation ou de la suppression définitive d'un gabarit biométrique. Rien n'est supprimé ; réitérez la même requête. Les nouvelles tentatives sont idempotentes et convergent vers un seul gabarit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Retryable": {
                    "value": {
                      "detail": "The biometric-template operation could not finish because an external store is unavailable. The operation is retryable."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/biometric-templates/delete/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"delete_all\": true, \"vendor_user_uuid\": \"2f7c1a9e-8b4d-4c6a-9e1f-3d5b7a9c1e2f\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.biometric_templates.batch_delete(\n    template_uuids=[\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\", \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.biometricTemplates.batchDelete({\n  template_uuids: [\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\", \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.BiometricTemplates.BatchDelete(ctx, didit.BiometricTemplatesBatchDeleteParams{\n\tTemplateUUIDs: didit.Some([]string{\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\", \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.BiometricTemplatesBatchDeleteParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.biometricTemplates().batchDelete(BiometricTemplatesBatchDeleteParams.builder()\n        .templateUuids(List.of(\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\", \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->biometricTemplates->batchDelete([\n    'template_uuids' => ['9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b', '1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.biometric_templates.batch_delete(template_uuids: [\"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\", \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\"])\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.BiometricTemplates.BatchDeleteAsync(new BiometricTemplatesBatchDeleteParams\n{\n    TemplateUuids = new string[] { \"9d2f4b6e-1c3a-4e8f-b7d5-0a1c2e3f4a5b\", \"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/kyb/shareholders/": {
      "post": {
        "summary": "Entreprise au registre KYB avec actionnaires (autonome)",
        "operationId": "post_v3_kyb_shareholders",
        "x-didit-sdk": {
          "resource": "kyb",
          "method": "list_shareholders",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "description": "Récupérez le profil Lite **ainsi que les actionnaires directs** (personnes physiques et personnes morales, avec leurs tranches d'actionnariat) d'un candidat renvoyé par `POST /v3/kyb/search/`.\n\n**Association avec la recherche.** Transmettez le `kyb_response_id` du candidat exactement tel qu'il a été renvoyé par une recherche de la même application. Effectuez la recherche au niveau que vous prévoyez d'acheter (`tier` sur `POST /v3/kyb/search/`), car la recherche s'exécute sur la chaîne de registres desservant ce niveau et une recherche Lite sans résultat ne prouve pas que le registre ne détient pas l'entreprise. Lorsque les données d'actionnariat du pays se trouvent dans un autre registre, Didit y retrouve l'entreprise à l'aide de son numéro d'immatriculation, sans frais supplémentaires.\n\n**Facturation.** Facturé au tarif Shareholders du pays - consultez [Tarifs des registres KYB](/fr/getting-started/kyb-registry-pricing). Lorsque le registre ne détient aucun enregistrement d'actionnaires pour l'entreprise (ou que le pays ne propose aucune donnée d'actionnariat), le profil Lite est livré et facturé à la place : consultez `registry_tier_delivered` et `registry_ownership_status`. Le solde est vérifié par rapport au prix Shareholders avant tout appel au registre (`403` en cas de solde insuffisant).\n\n**Disponibilité.** v3 uniquement. Chaque appel crée une session d'entreprise (son identifiant est le `request_id`).\n\n**Rapports en attente.** Lorsqu'un rapport est toujours en cours de préparation, ou que la section sur l'actionnariat n'a pas encore été récupérée auprès du registre, l'endpoint renvoie 202 Accepted, kyb_registry.fetch_status=pending, kyb_registry.registry_ownership_status=pending et registry_tier_delivered=null. Conservez request_id et appelez GET /v3/session/{request_id}/decision/ jusqu'à ce que registry_checks[0].company.fetch_status soit résolu. Didit finalise le rapport automatiquement et facture le niveau livré une fois qu'il est prêt. Ne renouvelez pas l'achat pendant qu'il est en attente ; chaque nouveau POST crée une requête distincte.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KYBRegistryCandidateRequest"
              },
              "example": {
                "kyb_response_id": "69aeeb95febb0f1704042259",
                "vendor_data": "company-1234"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/kyb/shareholders/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"kyb_response_id\": \"69aeeb95febb0f1704042259\",\n    \"vendor_data\": \"company-1234\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.kyb.list_shareholders(\n    kyb_response_id=\"69aeeb95febb0f1704042259\",\n    vendor_data=\"company-1234\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.kyb.listShareholders({\n  kyb_response_id: \"69aeeb95febb0f1704042259\",\n  vendor_data: \"company-1234\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.KYB.ListShareholders(ctx, didit.KYBRegistryCandidateRequest{\n\tKYBResponseID: \"69aeeb95febb0f1704042259\",\n\tVendorData:    didit.String(\"company-1234\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.KYBRegistryCandidateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.kyb().listShareholders(KYBRegistryCandidateRequest.builder()\n        .kybResponseId(\"69aeeb95febb0f1704042259\")\n        .vendorData(\"company-1234\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->kyb->listShareholders([\n    'kyb_response_id' => '69aeeb95febb0f1704042259',\n    'vendor_data' => 'company-1234',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.kyb.list_shareholders(\n  kyb_response_id: \"69aeeb95febb0f1704042259\",\n  vendor_data: \"company-1234\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Kyb.ListShareholdersAsync(new KYBRegistryCandidateRequest\n{\n    KybResponseId = \"69aeeb95febb0f1704042259\",\n    VendorData = \"company-1234\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Rapport d'entreprise renvoyé et facturé au niveau fourni. Les rapports d'actionnariat toujours en cours de préparation peuvent renvoyer 202 ; conservez request_id pour récupérer leur décision enregistrée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de la session d'entreprise créée pour cette récupération. L'enregistrement stocké (visible dans la console) continue d'être mis à jour si la résolution du registre intervient après la réponse."
                    },
                    "registry_tier_requested": {
                      "type": "string",
                      "enum": [
                        "basic",
                        "shareholders",
                        "ubo"
                      ],
                      "description": "Le niveau proposé par cet endpoint : `basic` (Lite) pour select, `shareholders`, `ubo`."
                    },
                    "registry_tier_delivered": {
                      "type": "string",
                      "enum": [
                        "basic",
                        "shareholders",
                        "ubo",
                        null
                      ],
                      "description": "Le niveau réellement fourni et facturé. Inférieur à celui demandé lorsque les registres du pays ne contiennent aucune donnée d'actionnariat, ou que le registre n'a aucun enregistrement d'actionnariat pour cette entreprise.",
                      "nullable": true
                    },
                    "kyb_registry": {
                      "type": "object",
                      "description": "Profil complet de l'entreprise issu du registre.",
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Identifiant Didit pour cet enregistrement d'entreprise."
                        },
                        "node_id": {
                          "type": "string",
                          "example": "feature_kyb_registry"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "Not Finished",
                            "Approved",
                            "Declined",
                            "In Review"
                          ],
                          "description": "Évaluation par Didit de la vérification au registre (par exemple `In Review` lorsque l'entreprise n'est pas active dans le registre ou que les données d'actionnariat n'ont pas pu être dérivées)."
                        },
                        "registry_status": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "active",
                            "dissolved",
                            "deregistered",
                            "see full details",
                            "authorised",
                            "appointed representative",
                            "unauthorised",
                            "inactive",
                            "no longer authorised",
                            "closed",
                            "struck off",
                            null
                          ],
                          "description": "Statut normalisé de l'entreprise tel que déclaré par le registre."
                        },
                        "data_resolved": {
                          "type": "boolean",
                          "description": "`true` dès que le registre a renvoyé le profil complet. `false` lorsque le registre était toujours en cours de traitement après interrogation — l'enregistrement stocké se complète automatiquement dès que le registre a terminé."
                        },
                        "company_name": {
                          "type": "string",
                          "example": "Tesco PLC"
                        },
                        "registration_number": {
                          "type": "string",
                          "nullable": true,
                          "example": "00445790"
                        },
                        "country_code": {
                          "type": "string",
                          "description": "ISO 3166-1 alpha-2.",
                          "example": "GB"
                        },
                        "region": {
                          "type": "string",
                          "nullable": true,
                          "description": "Code de subdivision lorsque le registre est régional (par exemple `CA` pour `US-CA`) ; vide dans le cas contraire."
                        },
                        "company_type": {
                          "type": "string",
                          "nullable": true,
                          "example": "Public Limited Company"
                        },
                        "incorporation_date": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "example": "1947-11-27"
                        },
                        "registered_address": {
                          "type": "string",
                          "nullable": true,
                          "example": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA"
                        },
                        "tax_number": {
                          "type": "string",
                          "nullable": true,
                          "example": "GB412 8925 93"
                        },
                        "risk_level": {
                          "type": "string",
                          "nullable": true,
                          "description": "Niveau de risque indiqué par le registre, lorsqu'il est disponible."
                        },
                        "verification_status": {
                          "type": "string",
                          "enum": [
                            "verified",
                            "failed",
                            "unknown"
                          ],
                          "nullable": true,
                          "description": "Statut de vérification inter-juridictions : `verified` lorsque le statut au registre établit la régularité (`active`), `failed` lorsqu'il indique que l'entreprise n'est plus en activité (par exemple `dissolved`), sinon `unknown`. `null` pour une entreprise qui ne provient pas d'un registre et tant qu'une sélection est encore `pending`."
                        },
                        "is_from_registry": {
                          "type": "boolean",
                          "description": "Toujours `true` pour cet endpoint — le profil a été récupéré auprès d'un registre officiel."
                        },
                        "fetch_status": {
                          "type": "string",
                          "enum": [
                            "pending",
                            "resolved"
                          ],
                          "description": "Cycle de vie de la récupération auprès du registre. Reflété par `data_resolved`."
                        },
                        "alternative_names": {
                          "type": "string",
                          "nullable": true,
                          "description": "Dénominations commerciales, alternatives, anciennes ou dans la langue d'origine de l'entreprise sous forme de texte, lorsqu'elles sont déclarées."
                        },
                        "nature_of_business": {
                          "type": "string",
                          "nullable": true,
                          "description": "Description de l'activité ou code de classification, lorsqu'ils sont communiqués."
                        },
                        "registered_capital": {
                          "type": "string",
                          "nullable": true
                        },
                        "registered_capital_amount": {
                          "type": "string",
                          "nullable": true,
                          "description": "Montant décimal sous forme de chaîne, lorsqu'il est renseigné."
                        },
                        "registered_capital_currency": {
                          "type": "string",
                          "nullable": true,
                          "description": "Code ISO 4217, lorsqu'il est renseigné."
                        },
                        "website": {
                          "type": "string",
                          "nullable": true,
                          "example": "https://www.tesco.com/"
                        },
                        "email": {
                          "type": "string",
                          "nullable": true,
                          "example": "customer.service@tesco.co.uk"
                        },
                        "phone": {
                          "type": "string",
                          "nullable": true,
                          "example": "03301231688"
                        },
                        "legal_entity_identifier": {
                          "type": "string",
                          "nullable": true,
                          "description": "LEI, lorsqu'il est déclaré."
                        },
                        "location_of_registration": {
                          "type": "string",
                          "nullable": true,
                          "description": "Registre/juridiction auprès duquel l'entreprise est immatriculée, lorsqu'il est renseigné."
                        },
                        "vat_number": {
                          "type": "string",
                          "nullable": true,
                          "description": "Numéro de TVA de l'UE, lorsqu'il est recueilli lors de l'étape de registre hébergée ou modifié ultérieurement. Au moment de la sélection, il n'est généralement pas encore défini — la validation de la TVA et de l'identifiant fiscal s'exécute lorsque l'utilisateur final soumet l'étape de registre dans le flux hébergé."
                        },
                        "vat_validation_status": {
                          "type": "string",
                          "enum": [
                            "valid",
                            "invalid",
                            "format_valid",
                            "invalid_format",
                            "could_not_validate",
                            "not_applicable"
                          ],
                          "description": "Résultat de la validation du numéro de TVA ou, s'il n'y en a pas, du `tax_number`, lors de la soumission au registre. `valid` / `invalid` : déterminé par le registre officiel du pays (VIES UE, Norvège, Suisse, Brésil, Colombie, Costa Rica, Équateur, Paraguay ; Pologne également par son registre national de TVA). `format_valid` / `invalid_format` : déterminé par les règles de format et de chiffre de contrôle du pays lorsqu'aucun registre ne peut être interrogé. `could_not_validate` : le registre était indisponible. `not_applicable` : pas de numéro, un pays sans registre ni règles, ou une session sandbox."
                        },
                        "vat_validated_number": {
                          "type": "string",
                          "nullable": true,
                          "description": "Le numéro qui a été vérifié, tel que la source le connaît (par exemple le numéro de TVA dérivé d'un SIREN français ou d'un RSIN néerlandais). `null` si aucune vérification n'a été effectuée."
                        },
                        "vat_validation_source": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "eu_vies",
                            "pl_vat_white_list",
                            "no_brreg",
                            "ch_uid_register",
                            "br_receita_federal",
                            "co_rues",
                            "cr_hacienda",
                            "ec_sri",
                            "py_dnit",
                            "format_rules",
                            null
                          ],
                          "description": "La source ayant déterminé `vat_validation_status` : un registre officiel ou `format_rules`. Vaut `null` si aucune vérification n'a été exécutée."
                        },
                        "vat_validated_name": {
                          "type": "string",
                          "nullable": true,
                          "description": "Nom enregistré auprès de la source ayant validé le numéro, lorsqu'elle en communique un. Défini uniquement lorsque le statut est `valid`."
                        },
                        "vat_validated_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Adresse enregistrée auprès de la source ayant validé le numéro, lorsqu'elle en divulgue une. Renseigné uniquement lorsque le statut est `valid`."
                        },
                        "vat_checked_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Horodatage de la vérification. `null` si aucune vérification n'a été exécutée."
                        },
                        "financial_summary": {
                          "type": "object",
                          "nullable": true,
                          "description": "Détails sur les actions/le capital indiqués par le registre (devise, nombre total d'actions, catégories d'actions), lorsqu'ils sont disponibles."
                        },
                        "officers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "name": {
                                "type": "string",
                                "example": "MELISSA BETHELL"
                              },
                              "designation": {
                                "type": "string",
                                "nullable": true,
                                "description": "Désignation brute au registre (ex. `Director`, `Secretary`)."
                              },
                              "role": {
                                "type": "string",
                                "description": "Rôle normalisé dérivé de la désignation. Ensemble complet du modèle à 17 valeurs ; l'analyse du registre sur cet endpoint renvoie généralement director, non_executive_director, secretary, chairman ou company_officer.",
                                "enum": [
                                  "director",
                                  "non_executive_director",
                                  "secretary",
                                  "chairman",
                                  "ubo",
                                  "shareholder",
                                  "representative",
                                  "founder",
                                  "legal_advisor",
                                  "authorized_signatory",
                                  "trustee",
                                  "beneficiary",
                                  "company_officer",
                                  "settlor",
                                  "protector",
                                  "investor",
                                  "other"
                                ]
                              },
                              "nationality": {
                                "type": "string",
                                "nullable": true
                              },
                              "is_active": {
                                "type": "boolean",
                                "description": "`false` lorsque le registre indique que le titulaire du mandat a démissionné."
                              },
                              "kyc_status": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "Approved",
                                  "Declined",
                                  "Pending",
                                  null
                                ],
                                "description": "Statut d'une session KYC associée, lorsqu'une session a été démarrée pour ce dirigeant. `null` sinon."
                              },
                              "kyc_session_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "URL de vérification de la session KYC associée, lorsqu'elle existe."
                              },
                              "first_name": {
                                "type": "string",
                                "nullable": true,
                                "description": "Prénom lorsqu'il est explicitement indiqué par le registre ; non déduit du nom complet."
                              },
                              "last_name": {
                                "type": "string",
                                "nullable": true,
                                "description": "Nom de famille lorsqu'il est explicitement indiqué par le registre."
                              },
                              "address": {
                                "type": "string",
                                "nullable": true,
                                "description": "Adresse du dirigeant indiquée par le registre."
                              },
                              "appointment_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date à laquelle le dirigeant a été nommé.",
                                "format": "date"
                              },
                              "termination_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de fin de mandat, lorsqu'elle est signalée.",
                                "format": "date"
                              },
                              "date_of_birth": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de naissance complète rapportée par le registre. Null lorsque seuls l'année ou le mois de naissance sont connus.",
                                "format": "date"
                              },
                              "date_of_birth_year": {
                                "type": "integer",
                                "nullable": true,
                                "minimum": 1,
                                "maximum": 9999,
                                "description": "Année de naissance indiquée par le registre, y compris lorsque la date complète n'est pas disponible."
                              },
                              "date_of_birth_month": {
                                "type": "integer",
                                "nullable": true,
                                "minimum": 1,
                                "maximum": 12,
                                "description": "Mois de naissance indiqué par le registre. Null lorsque seule l'année est connue."
                              }
                            }
                          },
                          "description": "Dirigeants, secrétaires et autres responsables extraits du registre."
                        },
                        "beneficial_owners": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "name": {
                                "type": "string"
                              },
                              "first_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "last_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "entity_type": {
                                "type": "string",
                                "enum": [
                                  "person",
                                  "company"
                                ],
                                "description": "Indique si le propriétaire est une personne physique ou une entité morale."
                              },
                              "roles": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Rôles normalisés (par exemple `ubo`, `shareholder`)."
                              },
                              "ownership_min_shares": {
                                "type": "string",
                                "nullable": true,
                                "description": "Limite inférieure de la fourchette d'actionnariat déclarée par le registre (par ex. `25%`)."
                              },
                              "ownership_max_shares": {
                                "type": "string",
                                "nullable": true,
                                "description": "Limite supérieure de la tranche d'actionnariat déclarée par le registre."
                              },
                              "is_active": {
                                "type": "boolean"
                              },
                              "kyc_status": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "Approved",
                                  "Declined",
                                  "Pending",
                                  null
                                ]
                              },
                              "kyc_session_url": {
                                "type": "string",
                                "nullable": true
                              },
                              "effective_ownership_percent": {
                                "type": "number",
                                "nullable": true,
                                "description": "Pourcentage d'actionnariat analysé (borne maximale, ou à défaut borne minimale)."
                              },
                              "company_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "registration_number": {
                                "type": "string",
                                "nullable": true
                              },
                              "country_of_birth": {
                                "type": "string",
                                "nullable": true
                              },
                              "email": {
                                "type": "string",
                                "nullable": true
                              },
                              "nationality": {
                                "type": "string",
                                "nullable": true
                              },
                              "designation": {
                                "type": "string",
                                "nullable": true
                              },
                              "voting_min_shares": {
                                "type": "string",
                                "nullable": true
                              },
                              "voting_max_shares": {
                                "type": "string",
                                "nullable": true
                              },
                              "date_of_birth": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de naissance complète lorsqu'elle est rapportée.",
                                "format": "date"
                              },
                              "appointment_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de nomination lorsqu'elle est déclarée.",
                                "format": "date"
                              },
                              "shareholding": {
                                "$ref": "#/components/schemas/KYBRegistryShareholding"
                              }
                            }
                          },
                          "description": "Bénéficiaires effectifs / personnes exerçant un contrôle significatif extraits du registre. Peut être vide lorsque le registre ne divulgue pas l'actionnariat."
                        },
                        "addresses": {
                          "type": "array",
                          "nullable": true,
                          "description": "Chaque adresse indiquée par le registre, sous un format canonique unique. Nul lorsqu'il n'en indique aucune.",
                          "items": {
                            "$ref": "#/components/schemas/KYBRegistryAddress"
                          }
                        },
                        "industries": {
                          "type": "array",
                          "nullable": true,
                          "description": "Les activités dans lesquelles le registre classe l'entreprise, sous une forme canonique. Null lorsqu'il n'en indique aucune.",
                          "items": {
                            "$ref": "#/components/schemas/KYBRegistryIndustry"
                          }
                        },
                        "accounts": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true,
                          "description": "Dates de dépôt au registre, lorsqu'elles sont disponibles. Les déclarations annuelles et les assemblées générales utilisent last_annual_return_date et last_agm_date ; elles sont distinctes des comptes financiers."
                        },
                        "registry_data": {
                          "$ref": "#/components/schemas/KYBRegistryData"
                        },
                        "user_provided_data": {
                          "type": "object",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint (utilisé par le flux KYB hébergé lorsque les utilisateurs finaux modifient les données de registre)."
                        },
                        "confirmed_by_user_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint."
                        },
                        "last_console_edit_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Défini lorsqu'un réviseur de la console modifie l'enregistrement ultérieurement."
                        },
                        "is_editable": {
                          "type": "boolean",
                          "description": "Indique si les données issues du registre peuvent encore être modifiées dans le flux hébergé ou la console."
                        },
                        "registry_tier_delivered": {
                          "type": "string",
                          "enum": [
                            "basic",
                            "shareholders",
                            "ubo",
                            null
                          ],
                          "description": "Identique au `registry_tier_delivered` de premier niveau.",
                          "nullable": true
                        },
                        "registry_ownership_status": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "not_requested",
                            "delivered",
                            "not_held",
                            "unavailable",
                            "pending",
                            null
                          ],
                          "description": "`delivered` lorsque les données d'actionnariat ont été reçues, `not_held` lorsque le registre d'actionnariat a répondu et ne répertorie pas cette entreprise (voir `registry_data.ownership_error`), `unavailable` lorsqu'un niveau d'actionnariat a été demandé mais que le registre n'en avait aucun pour cette entreprise ou n'a pas pu être interrogé (voir `registry_data.ownership_error`), `pending` lorsque la section relative à l'actionnariat n'a pas encore été récupérée auprès du registre et que Didit est toujours en train de la compléter, `not_requested` pour le niveau Lite."
                        },
                        "ownership": {
                          "$ref": "#/components/schemas/KYBRegistryOwnership"
                        },
                        "registry_tier": {
                          "type": "string",
                          "nullable": true,
                          "description": "Le niveau de registre commandé par le workflow : `basic`, `shareholders` ou `ubo`. Également dans `ownership.tier_requested`."
                        },
                        "registry_monitoring": {
                          "type": "object",
                          "nullable": true,
                          "description": "Le moniteur de registre le plus récent pour l'entreprise, ou `null` s'il n'en existe aucun.",
                          "properties": {
                            "uuid": {
                              "type": "string",
                              "format": "uuid"
                            },
                            "status": {
                              "type": "string"
                            },
                            "unavailable_reason": {
                              "type": "string",
                              "nullable": true
                            },
                            "enrolled_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "cancelled_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "last_bill_date": {
                              "type": "string",
                              "format": "date",
                              "nullable": true
                            },
                            "next_bill_date": {
                              "type": "string",
                              "format": "date",
                              "nullable": true
                            },
                            "last_event_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "events_count": {
                              "type": "integer"
                            },
                            "watched_fields": {
                              "description": "Les champs de l'entreprise que le moniteur surveille."
                            }
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Valeur renvoyée de `vendor_data` que vous avez envoyé."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "description": "Écho des `metadata` que vous avez envoyées."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "Resolved company": {
                    "summary": "Profil complet du registre (liste des dirigeants tronquée par souci de concision)",
                    "value": {
                      "request_id": "9d4f2c7a-1b3e-4a5c-8d6f-0e9a8b7c6d5e",
                      "kyb_registry": {
                        "uuid": "f1e2d3c4-b5a6-4789-9c0d-1e2f3a4b5c6d",
                        "node_id": "feature_kyb_registry",
                        "status": "In Review",
                        "registry_status": "active",
                        "data_resolved": true,
                        "company_name": "Tesco PLC",
                        "registration_number": "00445790",
                        "country_code": "GB",
                        "region": "",
                        "company_type": "Public Limited Company",
                        "incorporation_date": "1947-11-27",
                        "registered_address": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA",
                        "tax_number": "GB412 8925 93",
                        "risk_level": "low risk",
                        "verification_status": "verified",
                        "is_from_registry": true,
                        "fetch_status": "resolved",
                        "alternative_names": "TESCO STORES (HOLDINGS) PUBLIC LIMITED COMPANY",
                        "nature_of_business": null,
                        "registered_capital": null,
                        "registered_capital_amount": null,
                        "registered_capital_currency": null,
                        "website": "https://www.tesco.com/",
                        "email": "customer.service@tesco.co.uk",
                        "phone": "03301231688",
                        "legal_entity_identifier": null,
                        "location_of_registration": null,
                        "financial_summary": {
                          "currency": "Pound (£)",
                          "total_number_of_shares": "8174378721",
                          "meta_detail": {
                            "Class_Of_Share": "Ordinary"
                          }
                        },
                        "officers": [
                          {
                            "uuid": "a1b2c3d4-e5f6-4789-9a0b-1c2d3e4f5a6b",
                            "name": "CHRISTOPHER JON TAYLOR",
                            "designation": "Secretary",
                            "role": "secretary",
                            "nationality": null,
                            "is_active": true,
                            "kyc_status": null,
                            "kyc_session_url": null
                          },
                          {
                            "uuid": "b2c3d4e5-f6a7-4890-8b1c-2d3e4f5a6b7c",
                            "name": "MELISSA BETHELL",
                            "designation": "Director",
                            "role": "director",
                            "nationality": "British",
                            "is_active": true,
                            "kyc_status": null,
                            "kyc_session_url": null
                          }
                        ],
                        "beneficial_owners": [],
                        "addresses": [
                          {
                            "address": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA",
                            "type": "legal_entity_registry_address",
                            "description": "registered office address"
                          }
                        ],
                        "industries": null,
                        "accounts": {
                          "last_account": "26 February 2025",
                          "next_account": "26 February 2026",
                          "due_by_date": "26 August 2026"
                        },
                        "registry_data": {},
                        "user_provided_data": null,
                        "confirmed_by_user_at": null,
                        "last_console_edit_at": null,
                        "is_editable": true
                      },
                      "vendor_data": "company-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:45:00.000000+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les problèmes au niveau des champs utilisent l'enveloppe standard de DRF.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing kyb_response_id": {
                    "summary": "`kyb_response_id` est requis",
                    "value": {
                      "kyb_response_id": [
                        "This field is required."
                      ]
                    }
                  },
                  "save_api_request=false rejected": {
                    "summary": "Les sélections sont toujours enregistrées",
                    "value": {
                      "save_api_request": [
                        "KYB registry select must be saved so billing and retrieval can be tracked."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout filtrage ou appel à un fournisseur.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Rapport accepté et toujours en cours de traitement. Lorsqu'un rapport est encore en préparation, l'endpoint renvoie 202 Accepted, kyb_registry.fetch_status=pending et registry_tier_delivered=null. Conservez request_id et interrogez GET /v3/session/{request_id}/decision/ jusqu'à ce que registry_checks[0].company.fetch_status soit résolu. Didit finalise le rapport automatiquement et facture le niveau livré une fois qu'il est prêt. Ne répétez pas l'achat pendant qu'il est en attente ; chaque nouveau POST crée une requête distincte.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1v3~1kyb~1shareholders~1/post/responses/200/content/application~1json/schema"
                },
                "examples": {
                  "Pending (registry still resolving)": {
                    "summary": "Le rapport d'actionnariat est toujours en cours de traitement ; récupérer la décision enregistrée",
                    "value": {
                      "request_id": "9d4f2c7a-1b3e-4a5c-8d6f-0e9a8b7c6d5e",
                      "kyb_registry": {
                        "uuid": "7c0a4f7e-2b1d-4f6a-9c3e-8d5b2a1f0e9d",
                        "node_id": "feature_kyb_registry",
                        "status": "Not Finished",
                        "registry_status": null,
                        "data_resolved": false,
                        "company_name": "Example Holdings Limited",
                        "registration_number": "12345678",
                        "country_code": "HK",
                        "region": null,
                        "company_type": null,
                        "incorporation_date": null,
                        "registered_address": null,
                        "tax_number": null,
                        "risk_level": null,
                        "verification_status": null,
                        "is_from_registry": true,
                        "fetch_status": "pending",
                        "alternative_names": null,
                        "nature_of_business": null,
                        "registered_capital": null,
                        "registered_capital_amount": null,
                        "registered_capital_currency": null,
                        "website": null,
                        "email": null,
                        "phone": null,
                        "legal_entity_identifier": null,
                        "location_of_registration": null,
                        "financial_summary": {},
                        "officers": [],
                        "beneficial_owners": [],
                        "addresses": null,
                        "industries": null,
                        "accounts": null,
                        "registry_data": {},
                        "user_provided_data": null,
                        "confirmed_by_user_at": null,
                        "last_console_edit_at": null,
                        "is_editable": true,
                        "registry_tier_delivered": null,
                        "registry_ownership_status": "pending"
                      },
                      "vendor_data": "company-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:45:00.000000+00:00",
                      "registry_tier_delivered": null,
                      "registry_tier_requested": "shareholders"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/kyb/ubo/": {
      "post": {
        "summary": "Entreprise au registre KYB avec bénéficiaires effectifs finaux (autonome)",
        "operationId": "post_v3_kyb_ubo",
        "x-didit-sdk": {
          "resource": "kyb",
          "method": "list_ubos",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "description": "Récupérez le profil Lite, les actionnaires directs **et les bénéficiaires effectifs** résolus à travers la chaîne d'actionnariat (`registry_data.ubo_resolution` contient la chaîne des sociétés mères) d'un candidat renvoyé par `POST /v3/kyb/search/`.\n\n**Association avec la recherche.** Transmettez le `kyb_response_id` du candidat exactement tel qu'il a été renvoyé par une recherche de la même application. Effectuez la recherche au niveau que vous prévoyez d'acheter (`tier` sur `POST /v3/kyb/search/`), car la recherche s'exécute sur la chaîne de registres desservant ce niveau et une recherche Lite sans résultat ne prouve pas que le registre ne détient pas l'entreprise. Lorsque les données d'actionnariat du pays se trouvent dans un autre registre, Didit y retrouve l'entreprise à l'aide de son numéro d'immatriculation, sans frais supplémentaires.\n\n**Facturation.** Facturé au tarif UBO du pays - consultez [Tarifs des registres KYB](/fr/getting-started/kyb-registry-pricing). Le niveau livré est le plus élevé que le pays et le registre peuvent fournir : Shareholders lorsque le rapport résolu ne désigne aucune personne physique comme bénéficiaire effectif, Lite lorsqu'il n'existe aucun enregistrement d'actionnariat ; `registry_tier_delivered` indique ce qui a été facturé. Le solde est vérifié par rapport au prix UBO avant tout appel au registre (`403` en cas de solde insuffisant).\n\n**Disponibilité.** v3 uniquement. Chaque appel crée une session d'entreprise (son identifiant est le `request_id`).\n\n**Rapports en attente.** Lorsqu'un rapport est toujours en cours de préparation, ou que la section sur l'actionnariat n'a pas encore été récupérée auprès du registre, l'endpoint renvoie 202 Accepted, kyb_registry.fetch_status=pending, kyb_registry.registry_ownership_status=pending et registry_tier_delivered=null. Conservez request_id et appelez GET /v3/session/{request_id}/decision/ jusqu'à ce que registry_checks[0].company.fetch_status soit résolu. Didit finalise le rapport automatiquement et facture le niveau livré une fois qu'il est prêt. Ne renouvelez pas l'achat pendant qu'il est en attente ; chaque nouveau POST crée une requête distincte.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KYBRegistryCandidateRequest"
              },
              "example": {
                "kyb_response_id": "69aeeb95febb0f1704042259",
                "vendor_data": "company-1234"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/kyb/ubo/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"kyb_response_id\": \"69aeeb95febb0f1704042259\",\n    \"vendor_data\": \"company-1234\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.kyb.list_ubos(\n    kyb_response_id=\"69aeeb95febb0f1704042259\",\n    vendor_data=\"company-1234\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.kyb.listUbos({\n  kyb_response_id: \"69aeeb95febb0f1704042259\",\n  vendor_data: \"company-1234\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.KYB.ListUBOs(ctx, didit.KYBRegistryCandidateRequest{\n\tKYBResponseID: \"69aeeb95febb0f1704042259\",\n\tVendorData:    didit.String(\"company-1234\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.KYBRegistryCandidateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.kyb().listUbos(KYBRegistryCandidateRequest.builder()\n        .kybResponseId(\"69aeeb95febb0f1704042259\")\n        .vendorData(\"company-1234\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->kyb->listUbos([\n    'kyb_response_id' => '69aeeb95febb0f1704042259',\n    'vendor_data' => 'company-1234',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.kyb.list_ubos(\n  kyb_response_id: \"69aeeb95febb0f1704042259\",\n  vendor_data: \"company-1234\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Kyb.ListUbosAsync(new KYBRegistryCandidateRequest\n{\n    KybResponseId = \"69aeeb95febb0f1704042259\",\n    VendorData = \"company-1234\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Rapport d'entreprise renvoyé et facturé au niveau fourni. Les rapports d'actionnariat toujours en cours de préparation peuvent renvoyer 202 ; conservez request_id pour récupérer leur décision enregistrée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant de la session d'entreprise créée pour cette récupération. L'enregistrement stocké (visible dans la console) continue d'être mis à jour si la résolution du registre intervient après la réponse."
                    },
                    "registry_tier_requested": {
                      "type": "string",
                      "enum": [
                        "basic",
                        "shareholders",
                        "ubo"
                      ],
                      "description": "Le niveau proposé par cet endpoint : `basic` (Lite) pour select, `shareholders`, `ubo`."
                    },
                    "registry_tier_delivered": {
                      "type": "string",
                      "enum": [
                        "basic",
                        "shareholders",
                        "ubo",
                        null
                      ],
                      "description": "Le niveau réellement fourni et facturé. Inférieur à celui demandé lorsque les registres du pays ne contiennent aucune donnée d'actionnariat, lorsque le registre n'a aucun enregistrement d'actionnariat pour cette entreprise, ou lorsque le rapport résolu d'une requête `ubo` ne désigne aucune personne physique comme bénéficiaire effectif.",
                      "nullable": true
                    },
                    "kyb_registry": {
                      "type": "object",
                      "description": "Profil complet de l'entreprise issu du registre.",
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Identifiant Didit pour cet enregistrement d'entreprise."
                        },
                        "node_id": {
                          "type": "string",
                          "example": "feature_kyb_registry"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "Not Finished",
                            "Approved",
                            "Declined",
                            "In Review"
                          ],
                          "description": "Évaluation par Didit de la vérification au registre (par exemple `In Review` lorsque l'entreprise n'est pas active dans le registre ou que les données d'actionnariat n'ont pas pu être dérivées)."
                        },
                        "registry_status": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "active",
                            "dissolved",
                            "deregistered",
                            "see full details",
                            "authorised",
                            "appointed representative",
                            "unauthorised",
                            "inactive",
                            "no longer authorised",
                            "closed",
                            "struck off",
                            null
                          ],
                          "description": "Statut normalisé de l'entreprise tel que déclaré par le registre."
                        },
                        "data_resolved": {
                          "type": "boolean",
                          "description": "`true` dès que le registre a renvoyé le profil complet. `false` lorsque le registre était toujours en cours de traitement après interrogation — l'enregistrement stocké se complète automatiquement dès que le registre a terminé."
                        },
                        "company_name": {
                          "type": "string",
                          "example": "Tesco PLC"
                        },
                        "registration_number": {
                          "type": "string",
                          "nullable": true,
                          "example": "00445790"
                        },
                        "country_code": {
                          "type": "string",
                          "description": "ISO 3166-1 alpha-2.",
                          "example": "GB"
                        },
                        "region": {
                          "type": "string",
                          "nullable": true,
                          "description": "Code de subdivision lorsque le registre est régional (par exemple `CA` pour `US-CA`) ; vide dans le cas contraire."
                        },
                        "company_type": {
                          "type": "string",
                          "nullable": true,
                          "example": "Public Limited Company"
                        },
                        "incorporation_date": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "example": "1947-11-27"
                        },
                        "registered_address": {
                          "type": "string",
                          "nullable": true,
                          "example": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA"
                        },
                        "tax_number": {
                          "type": "string",
                          "nullable": true,
                          "example": "GB412 8925 93"
                        },
                        "risk_level": {
                          "type": "string",
                          "nullable": true,
                          "description": "Niveau de risque indiqué par le registre, lorsqu'il est disponible."
                        },
                        "verification_status": {
                          "type": "string",
                          "enum": [
                            "verified",
                            "failed",
                            "unknown"
                          ],
                          "nullable": true,
                          "description": "Statut de vérification inter-juridictions : `verified` lorsque le statut au registre établit la régularité (`active`), `failed` lorsqu'il indique que l'entreprise n'est plus en activité (par exemple `dissolved`), sinon `unknown`. `null` pour une entreprise qui ne provient pas d'un registre et tant qu'une sélection est encore `pending`."
                        },
                        "is_from_registry": {
                          "type": "boolean",
                          "description": "Toujours `true` pour cet endpoint — le profil a été récupéré auprès d'un registre officiel."
                        },
                        "fetch_status": {
                          "type": "string",
                          "enum": [
                            "pending",
                            "resolved"
                          ],
                          "description": "Cycle de vie de la récupération auprès du registre. Reflété par `data_resolved`."
                        },
                        "alternative_names": {
                          "type": "string",
                          "nullable": true,
                          "description": "Dénominations commerciales, alternatives, anciennes ou dans la langue d'origine de l'entreprise sous forme de texte, lorsqu'elles sont déclarées."
                        },
                        "nature_of_business": {
                          "type": "string",
                          "nullable": true,
                          "description": "Description de l'activité ou code de classification, lorsqu'ils sont communiqués."
                        },
                        "registered_capital": {
                          "type": "string",
                          "nullable": true
                        },
                        "registered_capital_amount": {
                          "type": "string",
                          "nullable": true,
                          "description": "Montant décimal sous forme de chaîne, lorsqu'il est renseigné."
                        },
                        "registered_capital_currency": {
                          "type": "string",
                          "nullable": true,
                          "description": "Code ISO 4217, lorsqu'il est renseigné."
                        },
                        "website": {
                          "type": "string",
                          "nullable": true,
                          "example": "https://www.tesco.com/"
                        },
                        "email": {
                          "type": "string",
                          "nullable": true,
                          "example": "customer.service@tesco.co.uk"
                        },
                        "phone": {
                          "type": "string",
                          "nullable": true,
                          "example": "03301231688"
                        },
                        "legal_entity_identifier": {
                          "type": "string",
                          "nullable": true,
                          "description": "LEI, lorsqu'il est déclaré."
                        },
                        "location_of_registration": {
                          "type": "string",
                          "nullable": true,
                          "description": "Registre/juridiction auprès duquel l'entreprise est immatriculée, lorsqu'il est renseigné."
                        },
                        "vat_number": {
                          "type": "string",
                          "nullable": true,
                          "description": "Numéro de TVA de l'UE, lorsqu'il est recueilli lors de l'étape de registre hébergée ou modifié ultérieurement. Au moment de la sélection, il n'est généralement pas encore défini — la validation de la TVA et de l'identifiant fiscal s'exécute lorsque l'utilisateur final soumet l'étape de registre dans le flux hébergé."
                        },
                        "vat_validation_status": {
                          "type": "string",
                          "enum": [
                            "valid",
                            "invalid",
                            "format_valid",
                            "invalid_format",
                            "could_not_validate",
                            "not_applicable"
                          ],
                          "description": "Résultat de la validation du numéro de TVA ou, s'il n'y en a pas, du `tax_number`, lors de la soumission au registre. `valid` / `invalid` : déterminé par le registre officiel du pays (VIES UE, Norvège, Suisse, Brésil, Colombie, Costa Rica, Équateur, Paraguay ; Pologne également par son registre national de TVA). `format_valid` / `invalid_format` : déterminé par les règles de format et de chiffre de contrôle du pays lorsqu'aucun registre ne peut être interrogé. `could_not_validate` : le registre était indisponible. `not_applicable` : pas de numéro, un pays sans registre ni règles, ou une session sandbox."
                        },
                        "vat_validated_number": {
                          "type": "string",
                          "nullable": true,
                          "description": "Le numéro qui a été vérifié, tel que la source le connaît (par exemple le numéro de TVA dérivé d'un SIREN français ou d'un RSIN néerlandais). `null` si aucune vérification n'a été effectuée."
                        },
                        "vat_validation_source": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "eu_vies",
                            "pl_vat_white_list",
                            "no_brreg",
                            "ch_uid_register",
                            "br_receita_federal",
                            "co_rues",
                            "cr_hacienda",
                            "ec_sri",
                            "py_dnit",
                            "format_rules",
                            null
                          ],
                          "description": "La source ayant déterminé `vat_validation_status` : un registre officiel ou `format_rules`. Vaut `null` si aucune vérification n'a été exécutée."
                        },
                        "vat_validated_name": {
                          "type": "string",
                          "nullable": true,
                          "description": "Nom enregistré auprès de la source ayant validé le numéro, lorsqu'elle en communique un. Défini uniquement lorsque le statut est `valid`."
                        },
                        "vat_validated_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Adresse enregistrée auprès de la source ayant validé le numéro, lorsqu'elle en divulgue une. Renseigné uniquement lorsque le statut est `valid`."
                        },
                        "vat_checked_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Horodatage de la vérification. `null` si aucune vérification n'a été exécutée."
                        },
                        "financial_summary": {
                          "type": "object",
                          "nullable": true,
                          "description": "Détails sur les actions/le capital indiqués par le registre (devise, nombre total d'actions, catégories d'actions), lorsqu'ils sont disponibles."
                        },
                        "officers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "name": {
                                "type": "string",
                                "example": "MELISSA BETHELL"
                              },
                              "designation": {
                                "type": "string",
                                "nullable": true,
                                "description": "Désignation brute au registre (ex. `Director`, `Secretary`)."
                              },
                              "role": {
                                "type": "string",
                                "description": "Rôle normalisé dérivé de la désignation. Ensemble complet du modèle à 17 valeurs ; l'analyse du registre sur cet endpoint renvoie généralement director, non_executive_director, secretary, chairman ou company_officer.",
                                "enum": [
                                  "director",
                                  "non_executive_director",
                                  "secretary",
                                  "chairman",
                                  "ubo",
                                  "shareholder",
                                  "representative",
                                  "founder",
                                  "legal_advisor",
                                  "authorized_signatory",
                                  "trustee",
                                  "beneficiary",
                                  "company_officer",
                                  "settlor",
                                  "protector",
                                  "investor",
                                  "other"
                                ]
                              },
                              "nationality": {
                                "type": "string",
                                "nullable": true
                              },
                              "is_active": {
                                "type": "boolean",
                                "description": "`false` lorsque le registre indique que le titulaire du mandat a démissionné."
                              },
                              "kyc_status": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "Approved",
                                  "Declined",
                                  "Pending",
                                  null
                                ],
                                "description": "Statut d'une session KYC associée, lorsqu'une session a été démarrée pour ce dirigeant. `null` sinon."
                              },
                              "kyc_session_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "URL de vérification de la session KYC associée, lorsqu'elle existe."
                              },
                              "first_name": {
                                "type": "string",
                                "nullable": true,
                                "description": "Prénom lorsqu'il est explicitement indiqué par le registre ; non déduit du nom complet."
                              },
                              "last_name": {
                                "type": "string",
                                "nullable": true,
                                "description": "Nom de famille lorsqu'il est explicitement indiqué par le registre."
                              },
                              "address": {
                                "type": "string",
                                "nullable": true,
                                "description": "Adresse du dirigeant indiquée par le registre."
                              },
                              "appointment_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date à laquelle le dirigeant a été nommé.",
                                "format": "date"
                              },
                              "termination_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de fin de mandat, lorsqu'elle est signalée.",
                                "format": "date"
                              },
                              "date_of_birth": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de naissance complète rapportée par le registre. Null lorsque seuls l'année ou le mois de naissance sont connus.",
                                "format": "date"
                              },
                              "date_of_birth_year": {
                                "type": "integer",
                                "nullable": true,
                                "minimum": 1,
                                "maximum": 9999,
                                "description": "Année de naissance indiquée par le registre, y compris lorsque la date complète n'est pas disponible."
                              },
                              "date_of_birth_month": {
                                "type": "integer",
                                "nullable": true,
                                "minimum": 1,
                                "maximum": 12,
                                "description": "Mois de naissance indiqué par le registre. Null lorsque seule l'année est connue."
                              }
                            }
                          },
                          "description": "Dirigeants, secrétaires et autres responsables extraits du registre."
                        },
                        "beneficial_owners": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "name": {
                                "type": "string"
                              },
                              "first_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "last_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "entity_type": {
                                "type": "string",
                                "enum": [
                                  "person",
                                  "company"
                                ],
                                "description": "Indique si le propriétaire est une personne physique ou une entité morale."
                              },
                              "roles": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Rôles normalisés (par exemple `ubo`, `shareholder`)."
                              },
                              "ownership_min_shares": {
                                "type": "string",
                                "nullable": true,
                                "description": "Limite inférieure de la fourchette d'actionnariat déclarée par le registre (par ex. `25%`)."
                              },
                              "ownership_max_shares": {
                                "type": "string",
                                "nullable": true,
                                "description": "Limite supérieure de la tranche d'actionnariat déclarée par le registre."
                              },
                              "is_active": {
                                "type": "boolean"
                              },
                              "kyc_status": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "Approved",
                                  "Declined",
                                  "Pending",
                                  null
                                ]
                              },
                              "kyc_session_url": {
                                "type": "string",
                                "nullable": true
                              },
                              "effective_ownership_percent": {
                                "type": "number",
                                "nullable": true,
                                "description": "Pourcentage d'actionnariat analysé (borne maximale, ou à défaut borne minimale)."
                              },
                              "company_name": {
                                "type": "string",
                                "nullable": true
                              },
                              "registration_number": {
                                "type": "string",
                                "nullable": true
                              },
                              "country_of_birth": {
                                "type": "string",
                                "nullable": true
                              },
                              "email": {
                                "type": "string",
                                "nullable": true
                              },
                              "nationality": {
                                "type": "string",
                                "nullable": true
                              },
                              "designation": {
                                "type": "string",
                                "nullable": true
                              },
                              "voting_min_shares": {
                                "type": "string",
                                "nullable": true
                              },
                              "voting_max_shares": {
                                "type": "string",
                                "nullable": true
                              },
                              "date_of_birth": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de naissance complète lorsqu'elle est rapportée.",
                                "format": "date"
                              },
                              "appointment_date": {
                                "type": "string",
                                "nullable": true,
                                "description": "Date de nomination lorsqu'elle est déclarée.",
                                "format": "date"
                              },
                              "shareholding": {
                                "$ref": "#/components/schemas/KYBRegistryShareholding"
                              }
                            }
                          },
                          "description": "Bénéficiaires effectifs / personnes exerçant un contrôle significatif extraits du registre. Peut être vide lorsque le registre ne divulgue pas l'actionnariat."
                        },
                        "addresses": {
                          "type": "array",
                          "nullable": true,
                          "description": "Chaque adresse indiquée par le registre, sous un format canonique unique. Nul lorsqu'il n'en indique aucune.",
                          "items": {
                            "$ref": "#/components/schemas/KYBRegistryAddress"
                          }
                        },
                        "industries": {
                          "type": "array",
                          "nullable": true,
                          "description": "Les activités dans lesquelles le registre classe l'entreprise, sous une forme canonique. Null lorsqu'il n'en indique aucune.",
                          "items": {
                            "$ref": "#/components/schemas/KYBRegistryIndustry"
                          }
                        },
                        "accounts": {
                          "type": "object",
                          "nullable": true,
                          "additionalProperties": true,
                          "description": "Dates de dépôt au registre, lorsqu'elles sont disponibles. Les déclarations annuelles et les assemblées générales utilisent last_annual_return_date et last_agm_date ; elles sont distinctes des comptes financiers."
                        },
                        "registry_data": {
                          "$ref": "#/components/schemas/KYBRegistryData"
                        },
                        "user_provided_data": {
                          "type": "object",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint (utilisé par le flux KYB hébergé lorsque les utilisateurs finaux modifient les données de registre)."
                        },
                        "confirmed_by_user_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Toujours `null` sur cet endpoint."
                        },
                        "last_console_edit_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true,
                          "description": "Défini lorsqu'un réviseur de la console modifie l'enregistrement ultérieurement."
                        },
                        "is_editable": {
                          "type": "boolean",
                          "description": "Indique si les données issues du registre peuvent encore être modifiées dans le flux hébergé ou la console."
                        },
                        "registry_tier_delivered": {
                          "type": "string",
                          "enum": [
                            "basic",
                            "shareholders",
                            "ubo",
                            null
                          ],
                          "description": "Identique au `registry_tier_delivered` de premier niveau.",
                          "nullable": true
                        },
                        "registry_ownership_status": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "not_requested",
                            "delivered",
                            "not_held",
                            "unavailable",
                            "pending",
                            null
                          ],
                          "description": "`delivered` lorsque les données d'actionnariat ont été reçues, `not_held` lorsque le registre d'actionnariat a répondu et ne répertorie pas cette entreprise (voir `registry_data.ownership_error`), `unavailable` lorsqu'un niveau d'actionnariat a été demandé mais que le registre n'en avait aucun pour cette entreprise ou n'a pas pu être interrogé (voir `registry_data.ownership_error`), `pending` lorsque la section relative à l'actionnariat n'a pas encore été récupérée auprès du registre et que Didit est toujours en train de la compléter, `not_requested` pour le niveau Lite."
                        },
                        "ownership": {
                          "$ref": "#/components/schemas/KYBRegistryOwnership"
                        },
                        "registry_tier": {
                          "type": "string",
                          "nullable": true,
                          "description": "Le niveau de registre commandé par le workflow : `basic`, `shareholders` ou `ubo`. Également dans `ownership.tier_requested`."
                        },
                        "registry_monitoring": {
                          "type": "object",
                          "nullable": true,
                          "description": "Le moniteur de registre le plus récent pour l'entreprise, ou `null` s'il n'en existe aucun.",
                          "properties": {
                            "uuid": {
                              "type": "string",
                              "format": "uuid"
                            },
                            "status": {
                              "type": "string"
                            },
                            "unavailable_reason": {
                              "type": "string",
                              "nullable": true
                            },
                            "enrolled_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "cancelled_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "last_bill_date": {
                              "type": "string",
                              "format": "date",
                              "nullable": true
                            },
                            "next_bill_date": {
                              "type": "string",
                              "format": "date",
                              "nullable": true
                            },
                            "last_event_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "events_count": {
                              "type": "integer"
                            },
                            "watched_fields": {
                              "description": "Les champs de l'entreprise que le moniteur surveille."
                            }
                          }
                        }
                      }
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Valeur renvoyée de `vendor_data` que vous avez envoyé."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true,
                      "description": "Écho des `metadata` que vous avez envoyées."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "Resolved company": {
                    "summary": "Profil complet du registre (liste des dirigeants tronquée par souci de concision)",
                    "value": {
                      "request_id": "9d4f2c7a-1b3e-4a5c-8d6f-0e9a8b7c6d5e",
                      "kyb_registry": {
                        "uuid": "f1e2d3c4-b5a6-4789-9c0d-1e2f3a4b5c6d",
                        "node_id": "feature_kyb_registry",
                        "status": "In Review",
                        "registry_status": "active",
                        "data_resolved": true,
                        "company_name": "Tesco PLC",
                        "registration_number": "00445790",
                        "country_code": "GB",
                        "region": "",
                        "company_type": "Public Limited Company",
                        "incorporation_date": "1947-11-27",
                        "registered_address": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA",
                        "tax_number": "GB412 8925 93",
                        "risk_level": "low risk",
                        "verification_status": "verified",
                        "is_from_registry": true,
                        "fetch_status": "resolved",
                        "alternative_names": "TESCO STORES (HOLDINGS) PUBLIC LIMITED COMPANY",
                        "nature_of_business": null,
                        "registered_capital": null,
                        "registered_capital_amount": null,
                        "registered_capital_currency": null,
                        "website": "https://www.tesco.com/",
                        "email": "customer.service@tesco.co.uk",
                        "phone": "03301231688",
                        "legal_entity_identifier": null,
                        "location_of_registration": null,
                        "financial_summary": {
                          "currency": "Pound (£)",
                          "total_number_of_shares": "8174378721",
                          "meta_detail": {
                            "Class_Of_Share": "Ordinary"
                          }
                        },
                        "officers": [
                          {
                            "uuid": "a1b2c3d4-e5f6-4789-9a0b-1c2d3e4f5a6b",
                            "name": "CHRISTOPHER JON TAYLOR",
                            "designation": "Secretary",
                            "role": "secretary",
                            "nationality": null,
                            "is_active": true,
                            "kyc_status": null,
                            "kyc_session_url": null
                          },
                          {
                            "uuid": "b2c3d4e5-f6a7-4890-8b1c-2d3e4f5a6b7c",
                            "name": "MELISSA BETHELL",
                            "designation": "Director",
                            "role": "director",
                            "nationality": "British",
                            "is_active": true,
                            "kyc_status": null,
                            "kyc_session_url": null
                          }
                        ],
                        "beneficial_owners": [],
                        "addresses": [
                          {
                            "address": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA",
                            "type": "legal_entity_registry_address",
                            "description": "registered office address"
                          }
                        ],
                        "industries": null,
                        "accounts": {
                          "last_account": "26 February 2025",
                          "next_account": "26 February 2026",
                          "due_by_date": "26 August 2026"
                        },
                        "registry_data": {
                          "ubo_resolution": {
                            "parent_chain": [],
                            "subsidiaries": [],
                            "unresolved": []
                          }
                        },
                        "user_provided_data": null,
                        "confirmed_by_user_at": null,
                        "last_console_edit_at": null,
                        "is_editable": true
                      },
                      "vendor_data": "company-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:45:00.000000+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les problèmes au niveau des champs utilisent l'enveloppe standard de DRF.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing kyb_response_id": {
                    "summary": "`kyb_response_id` est requis",
                    "value": {
                      "kyb_response_id": [
                        "This field is required."
                      ]
                    }
                  },
                  "save_api_request=false rejected": {
                    "summary": "Les sélections sont toujours enregistrées",
                    "value": {
                      "save_api_request": [
                        "KYB registry select must be saved so billing and retrieval can be tracked."
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission refusée. Renvoyé lorsque l'en-tête `x-api-key` est manquant, ainsi que lorsque le solde de l'organisation appelante ne permet pas de couvrir l'appel ; une clé incorrecte, révoquée ou expirée renvoie `401`. Une clé manquante renvoie `403` avec `{\"detail\": ...}` ; une clé incorrecte, révoquée ou expirée renvoie `401`. Les crédits insuffisants renvoient `403` avec `{\"error\": ...}` avant tout filtrage ou appel à un fournisseur.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide/révoquée",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Not enough credits": {
                    "summary": "Le solde de l'organisation ne peut pas couvrir l'appel",
                    "value": {
                      "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée. Les endpoints POST/PATCH/DELETE partagent un budget de 300 requêtes d'écriture par minute par clé API (la création de transactions et l'ingestion d'événements ont un budget distinct de 600). La réponse comporte les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` et `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Write rate limit exceeded": {
                    "summary": "Plus de 300 requêtes d'écriture au cours de la minute actuelle",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Rapport accepté et toujours en cours de traitement. Lorsqu'un rapport est encore en préparation, l'endpoint renvoie 202 Accepted, kyb_registry.fetch_status=pending et registry_tier_delivered=null. Conservez request_id et interrogez GET /v3/session/{request_id}/decision/ jusqu'à ce que registry_checks[0].company.fetch_status soit résolu. Didit finalise le rapport automatiquement et facture le niveau livré une fois qu'il est prêt. Ne répétez pas l'achat pendant qu'il est en attente ; chaque nouveau POST crée une requête distincte.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/paths/~1v3~1kyb~1ubo~1/post/responses/200/content/application~1json/schema"
                },
                "examples": {
                  "Pending (registry still resolving)": {
                    "summary": "Le rapport d'actionnariat est toujours en cours de traitement ; récupérer la décision enregistrée",
                    "value": {
                      "request_id": "9d4f2c7a-1b3e-4a5c-8d6f-0e9a8b7c6d5e",
                      "kyb_registry": {
                        "uuid": "7c0a4f7e-2b1d-4f6a-9c3e-8d5b2a1f0e9d",
                        "node_id": "feature_kyb_registry",
                        "status": "Not Finished",
                        "registry_status": null,
                        "data_resolved": false,
                        "company_name": "Example Holdings Limited",
                        "registration_number": "12345678",
                        "country_code": "HK",
                        "region": null,
                        "company_type": null,
                        "incorporation_date": null,
                        "registered_address": null,
                        "tax_number": null,
                        "risk_level": null,
                        "verification_status": null,
                        "is_from_registry": true,
                        "fetch_status": "pending",
                        "alternative_names": null,
                        "nature_of_business": null,
                        "registered_capital": null,
                        "registered_capital_amount": null,
                        "registered_capital_currency": null,
                        "website": null,
                        "email": null,
                        "phone": null,
                        "legal_entity_identifier": null,
                        "location_of_registration": null,
                        "financial_summary": {},
                        "officers": [],
                        "beneficial_owners": [],
                        "addresses": null,
                        "industries": null,
                        "accounts": null,
                        "registry_data": {},
                        "user_provided_data": null,
                        "confirmed_by_user_at": null,
                        "last_console_edit_at": null,
                        "is_editable": true,
                        "registry_tier_delivered": null,
                        "registry_ownership_status": "pending"
                      },
                      "vendor_data": "company-1234",
                      "metadata": null,
                      "created_at": "2026-06-11T10:45:00.000000+00:00",
                      "registry_tier_delivered": null,
                      "registry_tier_requested": "ubo"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/id-verification/wallets/": {
      "get": {
        "operationId": "list_wallets",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "description": "Chaque portefeuille Digital ID avec son endpoint de démarrage, ses pays, ses champs requis et indique si cette application peut le démarrer dans cet environnement maintenant. Être listé ne signifie pas être actif.",
        "summary": "Lister les portefeuilles d'identité numérique",
        "tags": [
          "Digital ID wallets"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletCatalogResponse"
                }
              }
            },
            "description": ""
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiClientCredentialsForbiddenErrorMessage"
                }
              }
            },
            "description": "Identifiants manquants (x-api-key ou Authorization: Bearer)."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request GET \\\n  --url https://verification.didit.me/v3/id-verification/wallets/ \\\n  --header 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.list()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.list();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.List(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().list();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->list();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.list\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.ListAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/id-verification/wallets/verifications/{request_id}/": {
      "get": {
        "operationId": "get_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "retrieve_verification",
          "auth": "api_key",
          "server": true
        },
        "description": "Statut et résultat d'une vérification de portefeuille : l'identité normalisée et les attributs propres au portefeuille une fois vérifiée, le code d'erreur une fois refusée, l'action suivante tant qu'elle est en attente. Une vérification ayant dépassé expires_at reçoit la décision timeout.",
        "summary": "Obtenir une vérification de portefeuille",
        "parameters": [
          {
            "in": "path",
            "name": "request_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Le request_id renvoyé par l'endpoint de démarrage.",
            "required": true
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "ftn",
                      "name": "Finnish Trust Network",
                      "issuing_authority": "Finnish banks and mobile operators (FTN)"
                    },
                    "country": "FIN",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiClientCredentialsForbiddenErrorMessage"
                }
              }
            },
            "description": "Identifiants manquants (x-api-key ou Authorization: Bearer)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur not_found : aucune vérification de portefeuille de cette application ne possède ce request_id."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request GET \\\n  --url https://verification.didit.me/v3/id-verification/wallets/verifications/REQUEST_ID/ \\\n  --header 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.retrieve_verification(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.retrieveVerification(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.RetrieveVerification(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().retrieveVerification(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->retrieveVerification('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.retrieve_verification(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.RetrieveVerificationAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/id-verification/wallets/verifications/{request_id}/poll/": {
      "post": {
        "operationId": "poll_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "poll_verification",
          "auth": "api_key",
          "server": true
        },
        "description": "Smart-ID et Mobile-ID : demande au fournisseur si l'utilisateur a confirmé, refusé ou laissé expirer la demande, et vérifie l'identité signée lors de la confirmation. Les portefeuilles par redirection s'exécutent dans le navigateur de l'utilisateur ; pour ceux-ci, cette opération se limite donc à relire la vérification. Renvoie la vérification telle qu'elle se présente par la suite.",
        "summary": "Interroger une vérification de portefeuille",
        "parameters": [
          {
            "in": "path",
            "name": "request_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Le request_id renvoyé par l'endpoint de démarrage.",
            "required": true
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "smart_id",
                      "name": "Smart-ID",
                      "issuing_authority": "SK ID Solutions"
                    },
                    "country": "EST",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "in_app",
                    "simulated": true,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "confirm_in_app",
                      "verification_code": "1234",
                      "poll_interval_seconds": 2
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiClientCredentialsForbiddenErrorMessage"
                }
              }
            },
            "description": "Identifiants manquants (x-api-key ou Authorization: Bearer)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur not_found : aucune vérification de portefeuille de cette application ne possède ce request_id."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/verifications/REQUEST_ID/poll/ \\\n  --header 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.poll_verification(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.pollVerification(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.PollVerification(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().pollVerification(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->pollVerification('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.poll_verification(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.PollVerificationAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/id-verification/wallets/verifications/{request_id}/cancel/": {
      "post": {
        "operationId": "cancel_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "cancel_verification",
          "auth": "api_key",
          "server": true
        },
        "description": "Retirer une vérification en attente : elle est refusée comme annulée et n'est jamais facturée. Une vérification déjà tranchée est renvoyée inchangée. Smart-ID et Mobile-ID : une annulation qui arrive pendant qu'une interrogation vérifie la connexion attend quelques secondes cette interrogation, puis la refuse, ou la renvoie vérifiée si l'utilisateur avait déjà confirmé. Une vérification que l'utilisateur est en train de finaliser à cet instant ne peut pas être annulée (409 verification_in_progress avec Retry-After) : réessayez après ce délai en secondes pour connaître son résultat.",
        "summary": "Annuler une vérification de portefeuille",
        "parameters": [
          {
            "in": "path",
            "name": "request_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Le request_id renvoyé par l'endpoint de démarrage.",
            "required": true
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "ftn",
                      "name": "Finnish Trust Network",
                      "issuing_authority": "Finnish banks and mobile operators (FTN)"
                    },
                    "country": "FIN",
                    "status": "Declined",
                    "outcome": "cancelled",
                    "error": "cancelled_by_customer",
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": null,
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiClientCredentialsForbiddenErrorMessage"
                }
              }
            },
            "description": "Identifiants manquants (x-api-key ou Authorization: Bearer)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur not_found : aucune vérification de portefeuille de cette application ne possède ce request_id."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur verification_in_progress : l'utilisateur est en train de finaliser cette connexion. L'en-tête Retry-After indique quand réessayer ; la nouvelle tentative renvoie la vérification ayant fait l'objet d'une décision."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/verifications/REQUEST_ID/cancel/ \\\n  --header 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.cancel_verification(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.cancelVerification(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.CancelVerification(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().cancelVerification(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->cancelVerification('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.cancel_verification(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.CancelVerificationAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/id-verification/wallets/mitid/": {
      "post": {
        "operationId": "start_mitid_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_mitid",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion MitID (Danish Agency for Digital Government ; DNK) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle diriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications en sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification MitID",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMitidWalletVerificationStartRequest"
              },
              "example": {
                "country": "DNK",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMitidWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMitidWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "mitid",
                      "name": "MitID",
                      "issuing_authority": "Danish Agency for Digital Government"
                    },
                    "country": "DNK",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/mitid/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"DNK\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_mitid(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"DNK\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startMitid({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"DNK\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartMitid(ctx, didit.IDWalletsStartMitidParams{\n\tBody: didit.DigitalIDWalletAPIMitidWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIMitidWalletVerificationStartCountryEnum(\"DNK\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiMitidWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiMitidWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startMitid(DigitalIdWalletApiMitidWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiMitidWalletVerificationStartCountryEnum.of(\"DNK\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startMitid([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'DNK',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_mitid(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"DNK\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartMitidAsync(new DigitalIdWalletApiMitidWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiMitidWalletVerificationStartCountryEnum(\"DNK\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "mitid"
      }
    },
    "/v3/id-verification/wallets/bankid-se/": {
      "post": {
        "operationId": "start_bankid_se_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_bankid_se",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion BankID (SWE) (Finansiell ID-Teknik / consortium bancaire ; SWE) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur retourne sur return_url avec request_id et result ajoutés. Récupérez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification BankID (SWE)",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidSeWalletVerificationStartRequest"
              },
              "example": {
                "country": "SWE",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidSeWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidSeWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "bankid_se",
                      "name": "BankID",
                      "issuing_authority": "Finansiell ID-Teknik / bank consortium"
                    },
                    "country": "SWE",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/bankid-se/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"SWE\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_bankid_se(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"SWE\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startBankidSe({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"SWE\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartBankidSe(ctx, didit.IDWalletsStartBankidSeParams{\n\tBody: didit.DigitalIDWalletAPIBankidSeWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountryEe9enum(\"SWE\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiBankidSeWalletVerificationStartRequest;\nimport me.didit.types.DigitalIdWalletApiCountryEe9Enum;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startBankidSe(DigitalIdWalletApiBankidSeWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountryEe9Enum.of(\"SWE\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startBankidSe([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'SWE',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_bankid_se(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"SWE\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartBankidSeAsync(new DigitalIdWalletApiBankidSeWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountryEe9Enum(\"SWE\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "bankid_se"
      }
    },
    "/v3/id-verification/wallets/bankid-no/": {
      "post": {
        "operationId": "start_bankid_no_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_bankid_no",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion BankID (NOR) (BankID BankAxept AS ; NOR) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur retourne sur return_url avec request_id et result ajoutés. Récupérez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification BankID (NOR)",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidNoWalletVerificationStartRequest"
              },
              "example": {
                "country": "NOR",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidNoWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidNoWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "bankid_no",
                      "name": "BankID",
                      "issuing_authority": "BankID BankAxept AS"
                    },
                    "country": "NOR",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/bankid-no/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"NOR\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_bankid_no(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"NOR\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startBankidNo({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"NOR\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartBankidNo(ctx, didit.IDWalletsStartBankidNoParams{\n\tBody: didit.DigitalIDWalletAPIBankidNoWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountryAfcEnum(\"NOR\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiBankidNoWalletVerificationStartRequest;\nimport me.didit.types.DigitalIdWalletApiCountryAfcEnum;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startBankidNo(DigitalIdWalletApiBankidNoWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountryAfcEnum.of(\"NOR\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startBankidNo([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'NOR',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_bankid_no(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"NOR\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartBankidNoAsync(new DigitalIdWalletApiBankidNoWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountryAfcEnum(\"NOR\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "bankid_no"
      }
    },
    "/v3/id-verification/wallets/vipps/": {
      "post": {
        "operationId": "start_vipps_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_vipps",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Vipps (Vipps MobilePay / BankID NO ; NOR) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox obtiennent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Vipps",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiVippsWalletVerificationStartRequest"
              },
              "example": {
                "country": "NOR",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiVippsWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiVippsWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "vipps",
                      "name": "Vipps",
                      "issuing_authority": "Vipps MobilePay / BankID NO"
                    },
                    "country": "NOR",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/vipps/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"NOR\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_vipps(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"NOR\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startVipps({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"NOR\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartVipps(ctx, didit.IDWalletsStartVippsParams{\n\tBody: didit.DigitalIDWalletAPIVippsWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountryAfcEnum(\"NOR\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiCountryAfcEnum;\nimport me.didit.types.DigitalIdWalletApiVippsWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startVipps(DigitalIdWalletApiVippsWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountryAfcEnum.of(\"NOR\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startVipps([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'NOR',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_vipps(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"NOR\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartVippsAsync(new DigitalIdWalletApiVippsWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountryAfcEnum(\"NOR\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "vipps"
      }
    },
    "/v3/id-verification/wallets/buypass/": {
      "post": {
        "operationId": "start_buypass_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_buypass",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion Buypass ID (Buypass AS ; NOR) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur retourne sur return_url avec request_id et result ajoutés. Récupérez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Buypass ID",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBuypassWalletVerificationStartRequest"
              },
              "example": {
                "country": "NOR",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBuypassWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBuypassWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "buypass",
                      "name": "Buypass ID",
                      "issuing_authority": "Buypass AS"
                    },
                    "country": "NOR",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/buypass/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"NOR\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_buypass(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"NOR\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startBuypass({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"NOR\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartBuypass(ctx, didit.IDWalletsStartBuypassParams{\n\tBody: didit.DigitalIDWalletAPIBuypassWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountryAfcEnum(\"NOR\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiBuypassWalletVerificationStartRequest;\nimport me.didit.types.DigitalIdWalletApiCountryAfcEnum;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startBuypass(DigitalIdWalletApiBuypassWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountryAfcEnum.of(\"NOR\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startBuypass([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'NOR',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_buypass(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"NOR\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartBuypassAsync(new DigitalIdWalletApiBuypassWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountryAfcEnum(\"NOR\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "buypass"
      }
    },
    "/v3/id-verification/wallets/itsme/": {
      "post": {
        "operationId": "start_itsme_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_itsme",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion itsme (Belgian Mobile ID ; BEL, LUX, NLD) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés en paramètres. Lisez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications en sandbox bénéficient d'une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification itsme",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiItsmeWalletVerificationStartRequest"
              },
              "example": {
                "country": "BEL",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiItsmeWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiItsmeWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "itsme",
                      "name": "itsme",
                      "issuing_authority": "Belgian Mobile ID"
                    },
                    "country": "BEL",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/itsme/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"BEL\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_itsme(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"BEL\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startItsme({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"BEL\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartItsme(ctx, didit.IDWalletsStartItsmeParams{\n\tBody: didit.DigitalIDWalletAPIItsmeWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.DigitalIDWalletAPIItsmeWalletVerificationStartCountryEnum(\"BEL\"),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiItsmeWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiItsmeWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startItsme(DigitalIdWalletApiItsmeWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiItsmeWalletVerificationStartCountryEnum.of(\"BEL\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startItsme([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'BEL',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_itsme(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"BEL\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartItsmeAsync(new DigitalIdWalletApiItsmeWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = \"BEL\",\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "itsme"
      }
    },
    "/v3/id-verification/wallets/idin/": {
      "post": {
        "operationId": "start_idin_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_idin",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion iDIN (banques néerlandaises (Currence iDIN) ; NLD) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés en paramètres. Lisez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications en sandbox bénéficient d'une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification iDIN",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiIdinWalletVerificationStartRequest"
              },
              "example": {
                "country": "NLD",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiIdinWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiIdinWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "idin",
                      "name": "iDIN",
                      "issuing_authority": "Dutch banks (Currence iDIN)"
                    },
                    "country": "NLD",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/idin/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"NLD\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_idin(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"NLD\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startIdin({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"NLD\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartIdin(ctx, didit.IDWalletsStartIdinParams{\n\tBody: didit.DigitalIDWalletAPIIdinWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIIdinWalletVerificationStartCountryEnum(\"NLD\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiIdinWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiIdinWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startIdin(DigitalIdWalletApiIdinWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiIdinWalletVerificationStartCountryEnum.of(\"NLD\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startIdin([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'NLD',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_idin(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"NLD\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartIdinAsync(new DigitalIdWalletApiIdinWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiIdinWalletVerificationStartCountryEnum(\"NLD\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "idin"
      }
    },
    "/v3/id-verification/wallets/ftn/": {
      "post": {
        "operationId": "start_ftn_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_ftn",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Finnish Trust Network (banques et opérateurs mobiles finlandais (FTN) ; FIN) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle diriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications en sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Finnish Trust Network",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFtnWalletVerificationStartRequest"
              },
              "example": {
                "country": "FIN",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFtnWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFtnWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "ftn",
                      "name": "Finnish Trust Network",
                      "issuing_authority": "Finnish banks and mobile operators (FTN)"
                    },
                    "country": "FIN",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/ftn/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"FIN\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_ftn(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"FIN\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startFtn({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"FIN\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartFtn(ctx, didit.IDWalletsStartFtnParams{\n\tBody: didit.DigitalIDWalletAPIFtnWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIFtnWalletVerificationStartCountryEnum(\"FIN\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiFtnWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiFtnWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startFtn(DigitalIdWalletApiFtnWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiFtnWalletVerificationStartCountryEnum.of(\"FIN\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startFtn([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'FIN',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_ftn(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"FIN\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartFtnAsync(new DigitalIdWalletApiFtnWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiFtnWalletVerificationStartCountryEnum(\"FIN\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "ftn"
      }
    },
    "/v3/id-verification/wallets/personalausweis/": {
      "post": {
        "operationId": "start_personalausweis_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_personalausweis",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Personalausweis (Bundesministerium des Innern (eID) ; DEU) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox obtiennent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Personalausweis",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiPersonalausweisWalletVerificationStartRequest"
              },
              "example": {
                "country": "DEU",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiPersonalausweisWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiPersonalausweisWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "personalausweis",
                      "name": "Personalausweis",
                      "issuing_authority": "Bundesministerium des Innern (eID)"
                    },
                    "country": "DEU",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/personalausweis/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"DEU\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_personalausweis(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"DEU\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startPersonalausweis({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"DEU\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartPersonalausweis(ctx, didit.IDWalletsStartPersonalausweisParams{\n\tBody: didit.DigitalIDWalletAPIPersonalausweisWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIPersonalausweisWalletVerificationStartCountryEnum(\"DEU\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiPersonalausweisWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiPersonalausweisWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startPersonalausweis(DigitalIdWalletApiPersonalausweisWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiPersonalausweisWalletVerificationStartCountryEnum.of(\"DEU\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startPersonalausweis([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'DEU',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_personalausweis(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"DEU\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartPersonalausweisAsync(new DigitalIdWalletApiPersonalausweisWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiPersonalausweisWalletVerificationStartCountryEnum(\"DEU\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "personalausweis"
      }
    },
    "/v3/id-verification/wallets/frejaid/": {
      "post": {
        "operationId": "start_frejaid_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_frejaid",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Freja eID (Freja eID Group ; SWE) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle diriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications en sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Freja eID",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFrejaidWalletVerificationStartRequest"
              },
              "example": {
                "country": "SWE",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFrejaidWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFrejaidWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "frejaid",
                      "name": "Freja eID",
                      "issuing_authority": "Freja eID Group"
                    },
                    "country": "SWE",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/frejaid/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"SWE\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_frejaid(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"SWE\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startFrejaid({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"SWE\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartFrejaid(ctx, didit.IDWalletsStartFrejaidParams{\n\tBody: didit.DigitalIDWalletAPIFrejaidWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountryEe9enum(\"SWE\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiCountryEe9Enum;\nimport me.didit.types.DigitalIdWalletApiFrejaidWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startFrejaid(DigitalIdWalletApiFrejaidWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountryEe9Enum.of(\"SWE\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startFrejaid([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'SWE',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_frejaid(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"SWE\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartFrejaidAsync(new DigitalIdWalletApiFrejaidWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountryEe9Enum(\"SWE\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "frejaid"
      }
    },
    "/v3/id-verification/wallets/uae-pass/": {
      "post": {
        "operationId": "start_uae_pass_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_uae_pass",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion UAE PASS (UAE Digital Government Authority ; ARE) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox obtiennent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification UAE PASS",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiUaePassWalletVerificationStartRequest"
              },
              "example": {
                "country": "ARE",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiUaePassWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiUaePassWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "uae_pass",
                      "name": "UAE PASS",
                      "issuing_authority": "UAE Digital Government Authority"
                    },
                    "country": "ARE",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/uae-pass/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"ARE\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_uae_pass(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"ARE\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startUaePass({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"ARE\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartUaePass(ctx, didit.IDWalletsStartUaePassParams{\n\tBody: didit.DigitalIDWalletAPIUaePassWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIUaePassWalletVerificationStartCountryEnum(\"ARE\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiUaePassWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiUaePassWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startUaePass(DigitalIdWalletApiUaePassWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiUaePassWalletVerificationStartCountryEnum.of(\"ARE\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startUaePass([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'ARE',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_uae_pass(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"ARE\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartUaePassAsync(new DigitalIdWalletApiUaePassWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiUaePassWalletVerificationStartCountryEnum(\"ARE\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "uae_pass"
      }
    },
    "/v3/id-verification/wallets/govbr/": {
      "post": {
        "operationId": "start_govbr_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_govbr",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion gov.br (Governo Federal do Brasil ; BRA) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox obtiennent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification gov.br",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGovbrWalletVerificationStartRequest"
              },
              "example": {
                "country": "BRA",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGovbrWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGovbrWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "govbr",
                      "name": "gov.br",
                      "issuing_authority": "Governo Federal do Brasil"
                    },
                    "country": "BRA",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/govbr/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"BRA\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_govbr(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"BRA\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startGovbr({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"BRA\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartGovbr(ctx, didit.IDWalletsStartGovbrParams{\n\tBody: didit.DigitalIDWalletAPIGovbrWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIGovbrWalletVerificationStartCountryEnum(\"BRA\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiGovbrWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiGovbrWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startGovbr(DigitalIdWalletApiGovbrWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiGovbrWalletVerificationStartCountryEnum.of(\"BRA\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startGovbr([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'BRA',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_govbr(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"BRA\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartGovbrAsync(new DigitalIdWalletApiGovbrWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiGovbrWalletVerificationStartCountryEnum(\"BRA\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "govbr"
      }
    },
    "/v3/id-verification/wallets/oneid/": {
      "post": {
        "operationId": "start_oneid_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_oneid",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion OneID (OneID (identité vérifiée par une banque britannique) ; GBR) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox obtiennent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification OneID",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiOneidWalletVerificationStartRequest"
              },
              "example": {
                "country": "GBR",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiOneidWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiOneidWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "oneid",
                      "name": "OneID",
                      "issuing_authority": "OneID (UK bank-verified identity)"
                    },
                    "country": "GBR",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/oneid/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"GBR\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_oneid(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"GBR\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startOneid({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"GBR\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartOneid(ctx, didit.IDWalletsStartOneidParams{\n\tBody: didit.DigitalIDWalletAPIOneidWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountry520enum(\"GBR\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiCountry520Enum;\nimport me.didit.types.DigitalIdWalletApiOneidWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startOneid(DigitalIdWalletApiOneidWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountry520Enum.of(\"GBR\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startOneid([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'GBR',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_oneid(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"GBR\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartOneidAsync(new DigitalIdWalletApiOneidWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountry520Enum(\"GBR\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "oneid"
      }
    },
    "/v3/id-verification/wallets/govuk-wallet/": {
      "post": {
        "operationId": "start_govuk_wallet_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_govuk_wallet",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion GOV.UK Wallet (UK Government Digital Service ; GBR) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle diriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications en sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification GOV.UK Wallet",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGovukWalletWalletVerificationStartRequest"
              },
              "example": {
                "country": "GBR",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGovukWalletWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGovukWalletWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "govuk_wallet",
                      "name": "GOV.UK Wallet",
                      "issuing_authority": "UK Government Digital Service"
                    },
                    "country": "GBR",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/govuk-wallet/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"GBR\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_govuk_wallet(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"GBR\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startGovukWallet({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"GBR\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartGovukWallet(ctx, didit.IDWalletsStartGovukWalletParams{\n\tBody: didit.DigitalIDWalletAPIGovukWalletWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountry520enum(\"GBR\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiCountry520Enum;\nimport me.didit.types.DigitalIdWalletApiGovukWalletWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startGovukWallet(DigitalIdWalletApiGovukWalletWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountry520Enum.of(\"GBR\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startGovukWallet([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'GBR',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_govuk_wallet(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"GBR\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartGovukWalletAsync(new DigitalIdWalletApiGovukWalletWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountry520Enum(\"GBR\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "govuk_wallet"
      }
    },
    "/v3/id-verification/wallets/smart-id/": {
      "post": {
        "operationId": "start_smart_id_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_smart_id",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Smart-ID (SK ID Solutions ; EST, LVA, LTU, BEL) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=confirm_in_app avec le code de comparaison à afficher à l'utilisateur ; l'utilisateur le confirme et saisit son code PIN dans l'application (ne collectez jamais le code PIN). Appelez POST /v3/id-verification/wallets/verifications/{request_id}/poll/ toutes les poll_interval_seconds secondes, ou appuyez-vous sur le webhook : Didit effectue également des interrogations en arrière-plan. Les applications sandbox obtiennent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Smart-ID",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiSmartIdWalletVerificationStartRequest"
              },
              "example": {
                "country": "EST",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "personal_code": "00000000000"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiSmartIdWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiSmartIdWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "smart_id",
                      "name": "Smart-ID",
                      "issuing_authority": "SK ID Solutions"
                    },
                    "country": "EST",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "in_app",
                    "simulated": true,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "confirm_in_app",
                      "verification_code": "1234",
                      "poll_interval_seconds": 2
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/smart-id/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"EST\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"personal_code\": \"00000000000\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_smart_id(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"EST\",\n    personal_code=\"00000000000\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startSmartId({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"EST\",\n  personal_code: \"00000000000\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartSmartID(ctx, didit.IDWalletsStartSmartIDParams{\n\tBody: didit.DigitalIDWalletAPISmartIDWalletVerificationStartRequest{\n\t\tVendorData:   didit.String(\"your-customer-reference\"),\n\t\tMetadata:     didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:      didit.DigitalIDWalletAPISmartIDWalletVerificationStartCountryEnum(\"EST\"),\n\t\tPersonalCode: \"00000000000\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiSmartIdWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiSmartIdWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startSmartId(DigitalIdWalletApiSmartIdWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiSmartIdWalletVerificationStartCountryEnum.of(\"EST\"))\n        .personalCode(\"00000000000\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startSmartId([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'EST',\n    'personal_code' => '00000000000',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_smart_id(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"EST\",\n  personal_code: \"00000000000\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartSmartIdAsync(new DigitalIdWalletApiSmartIdWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = \"EST\",\n    PersonalCode = \"00000000000\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "smart_id"
      }
    },
    "/v3/id-verification/wallets/mobile-id/": {
      "post": {
        "operationId": "start_mobile_id_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_mobile_id",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Mobile-ID (SK ID Solutions avec les opérateurs mobiles nationaux ; EST, LTU) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=confirm_in_app avec le code de comparaison à afficher à l'utilisateur ; l'utilisateur le confirme et saisit son code PIN dans l'application (ne collectez jamais le code PIN). Interrogez en POST /v3/id-verification/wallets/verifications/{request_id}/poll/ à chaque intervalle poll_interval_seconds, ou appuyez-vous sur le webhook : Didit effectue également un polling en arrière-plan. Les applications en sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Mobile-ID",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMobileIdWalletVerificationStartRequest"
              },
              "example": {
                "country": "EST",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "personal_code": "00000000000",
                "phone_number": "+37200000000"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMobileIdWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMobileIdWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "mobile_id",
                      "name": "Mobile-ID",
                      "issuing_authority": "SK ID Solutions with the national mobile operators"
                    },
                    "country": "EST",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "in_app",
                    "simulated": true,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "confirm_in_app",
                      "verification_code": "1234",
                      "poll_interval_seconds": 2
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/mobile-id/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"EST\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"personal_code\": \"00000000000\",\n  \"phone_number\": \"+37200000000\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_mobile_id(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"EST\",\n    personal_code=\"00000000000\",\n    phone_number=\"+37200000000\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startMobileId({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"EST\",\n  personal_code: \"00000000000\",\n  phone_number: \"+37200000000\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartMobileID(ctx, didit.IDWalletsStartMobileIDParams{\n\tBody: didit.DigitalIDWalletAPIMobileIDWalletVerificationStartRequest{\n\t\tVendorData:   didit.String(\"your-customer-reference\"),\n\t\tMetadata:     didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:      didit.DigitalIDWalletAPIMobileIDWalletVerificationStartCountryEnum(\"EST\"),\n\t\tPersonalCode: \"00000000000\",\n\t\tPhoneNumber:  \"+37200000000\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiMobileIdWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiMobileIdWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startMobileId(DigitalIdWalletApiMobileIdWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiMobileIdWalletVerificationStartCountryEnum.of(\"EST\"))\n        .personalCode(\"00000000000\")\n        .phoneNumber(\"+37200000000\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startMobileId([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'EST',\n    'personal_code' => '00000000000',\n    'phone_number' => '+37200000000',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_mobile_id(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"EST\",\n  personal_code: \"00000000000\",\n  phone_number: \"+37200000000\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartMobileIdAsync(new DigitalIdWalletApiMobileIdWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = \"EST\",\n    PersonalCode = \"00000000000\",\n    PhoneNumber = \"+37200000000\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "mobile_id"
      }
    },
    "/v3/id-verification/wallets/idcard-ee/": {
      "post": {
        "operationId": "start_idcard_ee_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_idcard_ee",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion par carte d'identité estonienne (Police and Border Guard Board (Estonie) ; EST) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur retourne sur return_url avec request_id et result ajoutés. Récupérez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification de la carte d'identité estonienne",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiIdcardEeWalletVerificationStartRequest"
              },
              "example": {
                "country": "EST",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiIdcardEeWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiIdcardEeWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "idcard_ee",
                      "name": "Estonian ID-card",
                      "issuing_authority": "Police and Border Guard Board (Estonia)"
                    },
                    "country": "EST",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/idcard-ee/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"EST\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_idcard_ee(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"EST\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startIdcardEe({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"EST\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartIdcardEe(ctx, didit.IDWalletsStartIdcardEeParams{\n\tBody: didit.DigitalIDWalletAPIIdcardEeWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIIdcardEeWalletVerificationStartCountryEnum(\"EST\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiIdcardEeWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiIdcardEeWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startIdcardEe(DigitalIdWalletApiIdcardEeWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiIdcardEeWalletVerificationStartCountryEnum.of(\"EST\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startIdcardEe([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'EST',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_idcard_ee(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"EST\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartIdcardEeAsync(new DigitalIdWalletApiIdcardEeWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiIdcardEeWalletVerificationStartCountryEnum(\"EST\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "idcard_ee"
      }
    },
    "/v3/id-verification/wallets/eparaksts-mobile/": {
      "post": {
        "operationId": "start_eparaksts_mobile_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_eparaksts_mobile",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion eParaksts mobile (LVRTC (Latvian State Radio and Television Centre) ; LVA) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox obtiennent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification mobile eParaksts",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiEparakstsMobileWalletVerificationStartRequest"
              },
              "example": {
                "country": "LVA",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiEparakstsMobileWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiEparakstsMobileWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "eparaksts_mobile",
                      "name": "eParaksts mobile",
                      "issuing_authority": "LVRTC (Latvian State Radio and Television Centre)"
                    },
                    "country": "LVA",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/eparaksts-mobile/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"LVA\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_eparaksts_mobile(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"LVA\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startEparakstsMobile({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"LVA\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartEparakstsMobile(ctx, didit.IDWalletsStartEparakstsMobileParams{\n\tBody: didit.DigitalIDWalletAPIEparakstsMobileWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIEparakstsMobileWalletVerificationStartCountryEnum(\"LVA\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiEparakstsMobileWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiEparakstsMobileWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startEparakstsMobile(DigitalIdWalletApiEparakstsMobileWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiEparakstsMobileWalletVerificationStartCountryEnum.of(\"LVA\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startEparakstsMobile([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'LVA',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_eparaksts_mobile(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"LVA\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartEparakstsMobileAsync(new DigitalIdWalletApiEparakstsMobileWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiEparakstsMobileWalletVerificationStartCountryEnum(\"LVA\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "eparaksts_mobile"
      }
    },
    "/v3/id-verification/wallets/bankid-cz/": {
      "post": {
        "operationId": "start_bankid_cz_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_bankid_cz",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Bank iD (Bankovní identita, a.s. ; CZE) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle diriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox bénéficient d'une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Bank iD",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidCzWalletVerificationStartRequest"
              },
              "example": {
                "country": "CZE",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidCzWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiBankidCzWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "bankid_cz",
                      "name": "Bank iD",
                      "issuing_authority": "Bankovní identita, a.s."
                    },
                    "country": "CZE",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/bankid-cz/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"CZE\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_bankid_cz(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"CZE\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startBankidCz({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"CZE\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartBankidCz(ctx, didit.IDWalletsStartBankidCzParams{\n\tBody: didit.DigitalIDWalletAPIBankidCzWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountryE2dEnum(\"CZE\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiBankidCzWalletVerificationStartRequest;\nimport me.didit.types.DigitalIdWalletApiCountryE2dEnum;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startBankidCz(DigitalIdWalletApiBankidCzWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountryE2dEnum.of(\"CZE\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startBankidCz([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'CZE',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_bankid_cz(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"CZE\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartBankidCzAsync(new DigitalIdWalletApiBankidCzWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountryE2dEnum(\"CZE\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "bankid_cz"
      }
    },
    "/v3/id-verification/wallets/mojeid/": {
      "post": {
        "operationId": "start_mojeid_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_mojeid",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion MojeID (CZ.NIC ; CZE) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox obtiennent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification MojeID",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMojeidWalletVerificationStartRequest"
              },
              "example": {
                "country": "CZE",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMojeidWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiMojeidWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "mojeid",
                      "name": "MojeID",
                      "issuing_authority": "CZ.NIC"
                    },
                    "country": "CZE",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/mojeid/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"CZE\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_mojeid(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"CZE\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startMojeid({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"CZE\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartMojeid(ctx, didit.IDWalletsStartMojeidParams{\n\tBody: didit.DigitalIDWalletAPIMojeidWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPICountryE2dEnum(\"CZE\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiCountryE2dEnum;\nimport me.didit.types.DigitalIdWalletApiMojeidWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startMojeid(DigitalIdWalletApiMojeidWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiCountryE2dEnum.of(\"CZE\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startMojeid([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'CZE',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_mojeid(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"CZE\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartMojeidAsync(new DigitalIdWalletApiMojeidWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiCountryE2dEnum(\"CZE\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "mojeid"
      }
    },
    "/v3/id-verification/wallets/diia/": {
      "post": {
        "operationId": "start_diia_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_diia",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion Diia (Ministère de la Transformation numérique de l'Ukraine ; UKR) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur retourne sur return_url avec request_id et result ajoutés. Récupérez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Diia",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiDiiaWalletVerificationStartRequest"
              },
              "example": {
                "country": "UKR",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiDiiaWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiDiiaWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "diia",
                      "name": "Diia",
                      "issuing_authority": "Ministry of Digital Transformation of Ukraine"
                    },
                    "country": "UKR",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/diia/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"UKR\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_diia(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"UKR\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startDiia({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"UKR\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartDiia(ctx, didit.IDWalletsStartDiiaParams{\n\tBody: didit.DigitalIDWalletAPIDiiaWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIDiiaWalletVerificationStartCountryEnum(\"UKR\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiDiiaWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiDiiaWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startDiia(DigitalIdWalletApiDiiaWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiDiiaWalletVerificationStartCountryEnum.of(\"UKR\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startDiia([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'UKR',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_diia(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"UKR\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartDiiaAsync(new DigitalIdWalletApiDiiaWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiDiiaWalletVerificationStartCountryEnum(\"UKR\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "diia"
      }
    },
    "/v3/id-verification/wallets/franceconnect/": {
      "post": {
        "operationId": "start_franceconnect_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_franceconnect",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion FranceConnect (DINUM (État français) ; FRA) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle diriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications en sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification FranceConnect",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFranceconnectWalletVerificationStartRequest"
              },
              "example": {
                "country": "FRA",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFranceconnectWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiFranceconnectWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "franceconnect",
                      "name": "FranceConnect",
                      "issuing_authority": "DINUM (French state)"
                    },
                    "country": "FRA",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/franceconnect/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"FRA\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_franceconnect(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"FRA\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startFranceconnect({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"FRA\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartFranceconnect(ctx, didit.IDWalletsStartFranceconnectParams{\n\tBody: didit.DigitalIDWalletAPIFranceconnectWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIFranceconnectWalletVerificationStartCountryEnum(\"FRA\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiFranceconnectWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiFranceconnectWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startFranceconnect(DigitalIdWalletApiFranceconnectWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiFranceconnectWalletVerificationStartCountryEnum.of(\"FRA\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startFranceconnect([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'FRA',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_franceconnect(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"FRA\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartFranceconnectAsync(new DigitalIdWalletApiFranceconnectWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiFranceconnectWalletVerificationStartCountryEnum(\"FRA\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "franceconnect"
      }
    },
    "/v3/id-verification/wallets/audkenni/": {
      "post": {
        "operationId": "start_audkenni_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_audkenni",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Auðkenni (Auðkenni (identifiant électronique islandais) ; ISL) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle diriger le navigateur de l'utilisateur ; l'utilisateur revient sur return_url avec request_id et result ajoutés. Consultez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox bénéficient d'une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Auðkenni",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiAudkenniWalletVerificationStartRequest"
              },
              "example": {
                "country": "ISL",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiAudkenniWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiAudkenniWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "audkenni",
                      "name": "Auðkenni",
                      "issuing_authority": "Auðkenni (Icelandic electronic ID)"
                    },
                    "country": "ISL",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/audkenni/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"ISL\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_audkenni(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"ISL\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startAudkenni({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"ISL\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartAudkenni(ctx, didit.IDWalletsStartAudkenniParams{\n\tBody: didit.DigitalIDWalletAPIAudkenniWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIAudkenniWalletVerificationStartCountryEnum(\"ISL\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiAudkenniWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiAudkenniWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startAudkenni(DigitalIdWalletApiAudkenniWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiAudkenniWalletVerificationStartCountryEnum.of(\"ISL\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startAudkenni([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'ISL',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_audkenni(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"ISL\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartAudkenniAsync(new DigitalIdWalletApiAudkenniWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiAudkenniWalletVerificationStartCountryEnum(\"ISL\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "audkenni"
      }
    },
    "/v3/id-verification/wallets/connectid/": {
      "post": {
        "operationId": "start_connectid_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_connectid",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion ConnectID (Australian Payments Plus ; AUS) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur retourne sur return_url avec request_id et result ajoutés. Récupérez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification ConnectID",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiConnectidWalletVerificationStartRequest"
              },
              "example": {
                "country": "AUS",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiConnectidWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiConnectidWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "connectid",
                      "name": "ConnectID",
                      "issuing_authority": "Australian Payments Plus"
                    },
                    "country": "AUS",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/connectid/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"AUS\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_connectid(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"AUS\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startConnectid({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"AUS\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartConnectid(ctx, didit.IDWalletsStartConnectidParams{\n\tBody: didit.DigitalIDWalletAPIConnectidWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.Some(didit.DigitalIDWalletAPIConnectidWalletVerificationStartCountryEnum(\"AUS\")),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiConnectidWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiConnectidWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startConnectid(DigitalIdWalletApiConnectidWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiConnectidWalletVerificationStartCountryEnum.of(\"AUS\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startConnectid([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'AUS',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_connectid(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"AUS\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartConnectidAsync(new DigitalIdWalletApiConnectidWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = new DigitalIdWalletApiConnectidWalletVerificationStartCountryEnum(\"AUS\"),\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "connectid"
      }
    },
    "/v3/id-verification/wallets/eudi/": {
      "post": {
        "operationId": "start_eudi_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_eudi",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrer une connexion EUDI Wallet (L'État membre de l'utilisateur ; l'émetteur diffère selon le pays ; AUT, BEL, BGR, HRV, CYP, CZE, DNK, EST, FIN, FRA, DEU, GRC, HUN, IRL, ITA, LVA, LTU, LUX, MLT, NLD, POL, PRT, ROU, SVK, SVN, ESP, SWE, ISL, LIE, NOR) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=redirect avec l'URL vers laquelle rediriger le navigateur de l'utilisateur ; l'utilisateur retourne sur return_url avec request_id et result ajoutés. Récupérez le résultat avec GET /v3/id-verification/wallets/verifications/{request_id}/ ou depuis le webhook, jamais depuis l'URL. Les applications sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification EUDI Wallet",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiEudiWalletVerificationStartRequest"
              },
              "example": {
                "country": "AUT",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "return_url": "https://app.example.com/identity/complete"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiEudiWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiEudiWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "eudi",
                      "name": "EUDI Wallet",
                      "issuing_authority": "The user's own member state; the issuer differs per country"
                    },
                    "country": "AUT",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "redirect",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "redirect",
                      "url": "https://wallet.example.com/authorize"
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/eudi/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"AUT\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"return_url\": \"https://app.example.com/identity/complete\"\n}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.id_wallets.start_eudi(\n    vendor_data=\"your-customer-reference\",\n    metadata={\"reference\": \"example\"},\n    country=\"AUT\",\n    return_url=\"https://app.example.com/identity/complete\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.idWallets.startEudi({\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"AUT\",\n  return_url: \"https://app.example.com/identity/complete\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IDWallets.StartEudi(ctx, didit.IDWalletsStartEudiParams{\n\tBody: didit.DigitalIDWalletAPIEudiWalletVerificationStartRequest{\n\t\tVendorData: didit.String(\"your-customer-reference\"),\n\t\tMetadata:   didit.Some(map[string]any{\"reference\": \"example\"}),\n\t\tCountry:    didit.DigitalIDWalletAPIEudiWalletVerificationStartCountryEnum(\"AUT\"),\n\t\tReturnURL:  \"https://app.example.com/identity/complete\",\n\t},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.DigitalIdWalletApiEudiWalletVerificationStartCountryEnum;\nimport me.didit.types.DigitalIdWalletApiEudiWalletVerificationStartRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.idWallets().startEudi(DigitalIdWalletApiEudiWalletVerificationStartRequest.builder()\n        .vendorData(\"your-customer-reference\")\n        .metadata(Map.of(\"reference\", \"example\"))\n        .country(DigitalIdWalletApiEudiWalletVerificationStartCountryEnum.of(\"AUT\"))\n        .returnUrl(\"https://app.example.com/identity/complete\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->idWallets->startEudi([\n    'vendor_data' => 'your-customer-reference',\n    'metadata' => ['reference' => 'example'],\n    'country' => 'AUT',\n    'return_url' => 'https://app.example.com/identity/complete',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.id_wallets.start_eudi(\n  vendor_data: \"your-customer-reference\",\n  metadata: { reference: \"example\" },\n  country: \"AUT\",\n  return_url: \"https://app.example.com/identity/complete\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.IdWallets.StartEudiAsync(new DigitalIdWalletApiEudiWalletVerificationStartRequest\n{\n    VendorData = \"your-customer-reference\",\n    Metadata = new Dictionary<string, object> { [\"reference\"] = \"example\" },\n    Country = \"AUT\",\n    ReturnUrl = \"https://app.example.com/identity/complete\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-wallet-id": "eudi"
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/teams/": {
      "get": {
        "summary": "Lister les équipes d'examen",
        "description": "Nécessite `list:cases` pour l'application demandée.",
        "operationId": "list_case_teams",
        "x-didit-sdk": {
          "resource": "cases.teams",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaseReviewTeam"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Nombre de correspondances, plafonné à 100. Suivez next pour continuer au-delà du plafond."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.teams.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.teams.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.Teams.ListAutoPaging(ctx, didit.CasesTeamsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().teams().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->teams->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.teams.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.Teams.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "summary": "Créer une équipe d'examen",
        "description": "Nécessite `write:cases` pour l'application demandée.",
        "operationId": "create_case_teams",
        "x-didit-sdk": {
          "resource": "cases.teams",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "responses": {
          "201": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseReviewTeam"
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseReviewTeamCreate"
              },
              "example": {
                "name": "AML analysts",
                "members": [
                  {
                    "user_id": "9a000000-0000-4000-8000-0000000000aa",
                    "capacity": 10
                  }
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.teams.create(\n    name=\"AML analysts\",\n    members=[{\n        \"user_id\": \"9a000000-0000-4000-8000-0000000000aa\",\n        \"capacity\": 10,\n    }],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.teams.create({\n  name: \"AML analysts\",\n  members: [{\n    user_id: \"9a000000-0000-4000-8000-0000000000aa\",\n    capacity: 10,\n  }],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Teams.Create(ctx, didit.CaseReviewTeamCreate{\n\tName: \"AML analysts\",\n\tMembers: []didit.CaseReviewTeamMemberParam{{\n\t\tUserID:   \"9a000000-0000-4000-8000-0000000000aa\",\n\t\tCapacity: didit.Int(10),\n\t}},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.CaseReviewTeamCreate;\nimport me.didit.types.CaseReviewTeamMember;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().teams().create(CaseReviewTeamCreate.builder()\n        .name(\"AML analysts\")\n        .members(List.of(CaseReviewTeamMember.builder()\n                .userId(\"9a000000-0000-4000-8000-0000000000aa\")\n                .capacity(10L)\n                .build()))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->teams->create([\n    'name' => 'AML analysts',\n    'members' => [[\n        'user_id' => '9a000000-0000-4000-8000-0000000000aa',\n        'capacity' => 10,\n    ]],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.teams.create(\n  name: \"AML analysts\",\n  members: [{\n    user_id: \"9a000000-0000-4000-8000-0000000000aa\",\n    capacity: 10,\n  }]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Teams.CreateAsync(new CaseReviewTeamCreate\n{\n    Name = \"AML analysts\",\n    Members = new CaseReviewTeamMember[]\n    {\n        new()\n        {\n            UserId = \"9a000000-0000-4000-8000-0000000000aa\",\n            Capacity = 10,\n        },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/fraud/checks/{check_id}/": {
      "get": {
        "operationId": "root_retrieve",
        "x-didit-sdk": {
          "resource": "fraud_checks",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "description": "Récupérer une vérification préalablement créée grâce à son `check_id`.",
        "summary": "Récupérer un contrôle de fraude",
        "parameters": [
          {
            "in": "path",
            "name": "check_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FraudCheckResponse"
                }
              }
            },
            "description": ""
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FraudClientCredentialsErrorMessage"
                }
              }
            },
            "description": ""
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FraudClientCredentialsForbiddenErrorMessage"
                }
              }
            },
            "description": ""
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "tags": [
          "Fraud Check"
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.fraud_checks.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.fraudChecks.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.FraudChecks.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.fraudChecks().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->fraudChecks->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.fraud_checks.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.FraudChecks.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/requests/": {
      "get": {
        "operationId": "organization_application_cases_requests_list",
        "x-didit-sdk": {
          "resource": "cases.requests",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Quel champ utiliser pour trier les résultats.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Nombre de résultats à retourner par page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "L'index initial à partir duquel renvoyer les résultats.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerMessagingPaginatedCaseRequestList"
                }
              }
            },
            "description": ""
          },
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.requests.list(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.requests.list(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.Requests.ListAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CasesRequestsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().requests().list(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->requests->list('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.requests.list(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.Requests.ListAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "operationId": "organization_application_cases_requests_create",
        "x-didit-sdk": {
          "resource": "cases.requests",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMessagingCaseRequestConfirmRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMessagingCaseRequestConfirmRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMessagingCaseRequestConfirmRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          },
          "400": {
            "description": "Entrées non valides, finalité non prise en charge, contact vérifié indisponible ou réponse immuable déjà existante."
          },
          "409": {
            "description": "L'aperçu a changé ou a expiré. Générez à nouveau l'aperçu avant de confirmer."
          },
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerMessagingCaseRequest"
                }
              }
            },
            "description": ""
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Confirmez l'aperçu signé exact dans un délai de 15 minutes. Seuls les modèles fixes et un contact vérifié par OTP appartenant au sujet du dossier sont acceptés. L'ID de requête rend les nouvelles tentatives idempotentes. La livraison est mise en file d'attente ; SENT, SIMULATED et UNKNOWN sont des résultats distincts. Une requête nécessitant une action passe le dossier à Awaiting user. Une mise à jour de l'examen laisse son statut inchangé.",
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.requests.create(\n    \"11111111-2222-3333-4444-555555555555\",\n    contact_id=\"11111111-2222-3333-4444-555555555555\",\n    purpose=\"identity_document\",\n    request_id=\"11111111-2222-3333-4444-555555555555\",\n    expires_at=\"2026-01-15T10:00:00Z\",\n    preview_token=\"your-preview-token\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.requests.create(\"11111111-2222-3333-4444-555555555555\", {\n  contact_id: \"11111111-2222-3333-4444-555555555555\",\n  purpose: \"identity_document\",\n  request_id: \"11111111-2222-3333-4444-555555555555\",\n  expires_at: \"2026-01-15T10:00:00Z\",\n  preview_token: \"your-preview-token\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Requests.Create(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CustomerMessagingCaseRequestConfirmRequest{\n\tContactID:    \"11111111-2222-3333-4444-555555555555\",\n\tPurpose:      didit.CustomerMessagingPurposeEnum(\"identity_document\"),\n\tRequestID:    \"11111111-2222-3333-4444-555555555555\",\n\tExpiresAt:    time.Date(2026, 1, 15, 10, 0, 0, 0, time.UTC),\n\tPreviewToken: \"your-preview-token\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.OffsetDateTime;\nimport me.didit.Didit;\nimport me.didit.types.CustomerMessagingCaseRequestConfirmRequest;\nimport me.didit.types.CustomerMessagingPurposeEnum;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().requests().create(\"11111111-2222-3333-4444-555555555555\", CustomerMessagingCaseRequestConfirmRequest.builder()\n        .contactId(\"11111111-2222-3333-4444-555555555555\")\n        .purpose(CustomerMessagingPurposeEnum.of(\"identity_document\"))\n        .requestId(\"11111111-2222-3333-4444-555555555555\")\n        .expiresAt(OffsetDateTime.parse(\"2026-01-15T10:00:00Z\"))\n        .previewToken(\"your-preview-token\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->requests->create('11111111-2222-3333-4444-555555555555', [\n    'contact_id' => '11111111-2222-3333-4444-555555555555',\n    'purpose' => 'identity_document',\n    'request_id' => '11111111-2222-3333-4444-555555555555',\n    'expires_at' => '2026-01-15T10:00:00Z',\n    'preview_token' => 'your-preview-token',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.requests.create(\n  \"11111111-2222-3333-4444-555555555555\",\n  contact_id: \"11111111-2222-3333-4444-555555555555\",\n  purpose: \"identity_document\",\n  request_id: \"11111111-2222-3333-4444-555555555555\",\n  expires_at: \"2026-01-15T10:00:00Z\",\n  preview_token: \"your-preview-token\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Requests.CreateAsync(\"11111111-2222-3333-4444-555555555555\", new CustomerMessagingCaseRequestConfirmRequest\n{\n    ContactId = \"11111111-2222-3333-4444-555555555555\",\n    Purpose = \"identity_document\",\n    RequestId = \"11111111-2222-3333-4444-555555555555\",\n    ExpiresAt = DateTimeOffset.Parse(\"2026-01-15T10:00:00Z\"),\n    PreviewToken = \"your-preview-token\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/fraud/checks/": {
      "post": {
        "operationId": "create_fraud_check",
        "x-didit-sdk": {
          "resource": "fraud_checks",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "description": "Soumettez un ou plusieurs identifiants typés et recevez en une seule réponse une normalisation, un enrichissement récent, une validation faisant autorité lorsque le pays et le type d'identifiant sont couverts, des dimensions de risque indépendantes et une recommandation.\n\nCes profils prennent en charge les vérifications d'identifiants. La liaison d'identité basée sur un selfie (`biometric_identity`) requiert la version de profil `2026-09-14.2` et un CPF brésilien ; elle ne s'exécute qu'avec le consentement de l'utilisateur et lorsque votre organisation y a droit. Les versions antérieures la signalent comme `not_available_in_profile_version`. Les modules ne pouvant pas s'exécuter sont signalés comme ignorés avec une raison déterministe ; une source n'ayant pas pu répondre n'est jamais signalée comme une non-concordance d'identité.",
        "summary": "Exécuter un contrôle de fraude",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/FraudCheckRequestRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FraudCheckRequestRequest"
              },
              "example": {
                "client_reference": "review-attempt-001",
                "subject": {
                  "identifiers": [
                    {
                      "type": "email",
                      "value": "applicant@example.com"
                    }
                  ],
                  "attributes": {
                    "first_name": "Alex",
                    "last_name": "Example"
                  }
                },
                "checks": {
                  "include": [
                    "networks_same_org",
                    "networks_cross_org",
                    "email_risk"
                  ]
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/FraudCheckRequestRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FraudCheckResponse"
                }
              }
            },
            "description": ""
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FraudClientCredentialsErrorMessage"
                }
              }
            },
            "description": ""
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FraudClientCredentialsForbiddenErrorMessage"
                }
              }
            },
            "description": ""
          },
          "409": {
            "description": "Conflit, renvoyé sans facturation : la valeur `client_reference` a déjà été utilisée avec un corps de requête différent ; un contrôle avec la même valeur `client_reference` est toujours en cours d'exécution (réessayez après `Retry-After` secondes avec la même référence) ; ou la vérification à laquelle ce contrôle est associé a été supprimée avant la fin du contrôle.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                },
                "examples": {
                  "different_body": {
                    "summary": "Référence réutilisée avec un corps de requête différent",
                    "value": {
                      "error": "client_reference has already been used with a different request body."
                    }
                  },
                  "still_running": {
                    "summary": "Une vérification portant cette référence est toujours en cours d'exécution",
                    "value": {
                      "error": "A check with this client_reference is already running. Retry with the same reference later."
                    }
                  },
                  "verification_deleted": {
                    "summary": "La vérification a été supprimée avant la fin du contrôle",
                    "value": {
                      "error": "This verification was deleted before the check completed."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer, envoyées lorsqu'une vérification avec le même `client_reference` est toujours en cours.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "tags": [
          "Fraud Check"
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.fraud_checks.create(\n    client_reference=\"review-attempt-001\",\n    subject={\n        \"identifiers\": [{\n            \"type\": \"email\",\n            \"value\": \"applicant@example.com\",\n        }],\n        \"attributes\": {\n            \"first_name\": \"Alex\",\n            \"last_name\": \"Example\",\n        },\n    },\n    checks={\n        \"include\": [\"networks_same_org\", \"networks_cross_org\", \"email_risk\"],\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.fraudChecks.create({\n  client_reference: \"review-attempt-001\",\n  subject: {\n    identifiers: [{\n      type: \"email\",\n      value: \"applicant@example.com\",\n    }],\n    attributes: {\n      first_name: \"Alex\",\n      last_name: \"Example\",\n    },\n  },\n  checks: {\n    include: [\"networks_same_org\", \"networks_cross_org\", \"email_risk\"],\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.FraudChecks.Create(ctx, didit.FraudCheckRequestRequest{\n\tClientReference: didit.String(\"review-attempt-001\"),\n\tSubject: didit.FraudCheckSubjectRequest{\n\t\tIdentifiers: []didit.FraudCheckIdentifierRequest{{\n\t\t\tType:  didit.FraudTypeEnum(\"email\"),\n\t\t\tValue: \"applicant@example.com\",\n\t\t}},\n\t\tAttributes: didit.Some(didit.FraudCheckAttributesRequest{\n\t\t\tFirstName: didit.String(\"Alex\"),\n\t\t\tLastName:  didit.String(\"Example\"),\n\t\t}),\n\t},\n\tChecks: didit.Some(didit.FraudCheckModuleSelectionRequest{\n\t\tInclude: didit.Some([]didit.FraudExcludeEnum{didit.FraudExcludeEnum(\"networks_same_org\"), didit.FraudExcludeEnum(\"networks_cross_org\"), didit.FraudExcludeEnum(\"email_risk\")}),\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.FraudCheckAttributesRequest;\nimport me.didit.types.FraudCheckIdentifierRequest;\nimport me.didit.types.FraudCheckModuleSelectionRequest;\nimport me.didit.types.FraudCheckRequestRequest;\nimport me.didit.types.FraudCheckSubjectRequest;\nimport me.didit.types.FraudExcludeEnum;\nimport me.didit.types.FraudTypeEnum;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.fraudChecks().create(FraudCheckRequestRequest.builder()\n        .clientReference(\"review-attempt-001\")\n        .subject(FraudCheckSubjectRequest.builder()\n                .identifiers(List.of(FraudCheckIdentifierRequest.builder()\n                        .type(FraudTypeEnum.of(\"email\"))\n                        .value(\"applicant@example.com\")\n                        .build()))\n                .attributes(FraudCheckAttributesRequest.builder()\n                        .firstName(\"Alex\")\n                        .lastName(\"Example\")\n                        .build())\n                .build())\n        .checks(FraudCheckModuleSelectionRequest.builder()\n                .include(List.of(FraudExcludeEnum.of(\"networks_same_org\"), FraudExcludeEnum.of(\"networks_cross_org\"), FraudExcludeEnum.of(\"email_risk\")))\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->fraudChecks->create([\n    'client_reference' => 'review-attempt-001',\n    'subject' => [\n        'identifiers' => [[\n            'type' => 'email',\n            'value' => 'applicant@example.com',\n        ]],\n        'attributes' => [\n            'first_name' => 'Alex',\n            'last_name' => 'Example',\n        ],\n    ],\n    'checks' => [\n        'include' => ['networks_same_org', 'networks_cross_org', 'email_risk'],\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.fraud_checks.create(\n  client_reference: \"review-attempt-001\",\n  subject: {\n    identifiers: [{\n      type: \"email\",\n      value: \"applicant@example.com\",\n    }],\n    attributes: {\n      first_name: \"Alex\",\n      last_name: \"Example\",\n    },\n  },\n  checks: {\n    include: [\"networks_same_org\", \"networks_cross_org\", \"email_risk\"],\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.FraudChecks.CreateAsync(new FraudCheckRequestRequest\n{\n    ClientReference = \"review-attempt-001\",\n    Subject = new()\n    {\n        Identifiers = new FraudCheckIdentifierRequest[]\n        {\n            new()\n            {\n                Type = \"email\",\n                Value = \"applicant@example.com\",\n            },\n        },\n        Attributes = new FraudCheckAttributesRequest\n        {\n            FirstName = \"Alex\",\n            LastName = \"Example\",\n        },\n    },\n    Checks = new FraudCheckModuleSelectionRequest\n    {\n        Include = new FraudExcludeEnum[] { \"networks_same_org\", \"networks_cross_org\", \"email_risk\" },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/requests/{request_uuid}/cancel/": {
      "post": {
        "operationId": "organization_application_cases_requests_cancel_create",
        "x-didit-sdk": {
          "resource": "cases.requests",
          "method": "cancel",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "request_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerMessagingCaseRequest"
                }
              }
            },
            "description": ""
          },
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          },
          "400": {
            "description": "Entrées non valides, finalité non prise en charge, contact vérifié indisponible ou réponse immuable déjà existante."
          },
          "409": {
            "description": "L'aperçu a changé ou a expiré. Générez à nouveau l'aperçu avant de confirmer."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.requests.cancel(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.requests.cancel(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Requests.Cancel(ctx, \"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().requests().cancel(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->requests->cancel('11111111-2222-3333-4444-555555555555', '11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.requests.cancel(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Requests.CancelAsync(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/requests/options/": {
      "get": {
        "operationId": "organization_application_cases_requests_options_retrieve",
        "x-didit-sdk": {
          "resource": "cases.requests",
          "method": "retrieve_options",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerMessagingCaseRequestOptions"
                }
              }
            },
            "description": ""
          },
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.requests.retrieve_options(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.requests.retrieveOptions(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Requests.RetrieveOptions(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().requests().retrieveOptions(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->requests->retrieveOptions('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.requests.retrieve_options(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Requests.RetrieveOptionsAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/requests/{request_uuid}/attachment/": {
      "get": {
        "operationId": "organization_application_cases_requests_attachment_retrieve",
        "x-didit-sdk": {
          "resource": "cases.requests",
          "method": "retrieve_attachment",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "request_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            },
            "description": ""
          },
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\ncontent = client.cases.requests.retrieve_attachment(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"11111111-2222-3333-4444-555555555555\",\n)\nwith open(\"download.png\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst content = await didit.cases.requests.retrieveAttachment(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n);\nawait writeFile(\"download.png\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresp, err := client.Cases.Requests.RetrieveAttachment(ctx, \"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.png\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.cases().requests().retrieveAttachment(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\")\n        .writeTo(Path.of(\"download.png\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$content = $didit->cases->requests->retrieveAttachment('11111111-2222-3333-4444-555555555555', '11111111-2222-3333-4444-555555555555');\n$content->saveTo('download.png');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ncontent = didit.cases.requests.retrieve_attachment(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\"\n)\nFile.binwrite(\"download.png\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar content = await client.Cases.Requests.RetrieveAttachmentAsync(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nawait content.SaveToAsync(\"download.png\");"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/routing-rules/{record_uuid}/history/": {
      "get": {
        "operationId": "list_case_routing_rule_history",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "list_history",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "record_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Quel champ utiliser pour trier les résultats.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Nombre de résultats à retourner par page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "L'index initial à partir duquel renvoyer les résultats.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "tags": [
          "Case Assignment"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingPublicationPaginatedPolicyRevisionList"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "L'accès au dossier est requis."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.routing_rules.list_history(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.routingRules.listHistory(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.RoutingRules.ListHistoryAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CasesRoutingRulesListHistoryParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().routingRules().listHistory(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->routingRules->listHistory('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.routing_rules.list_history(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.RoutingRules.ListHistoryAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/resubmission-preview/": {
      "post": {
        "summary": "Prévisualiser un e-mail de nouvelle soumission",
        "description": "Générez un aperçu de l'e-mail qui accompagnerait une nouvelle soumission KYC ou KYB sans modifier la session, réinitialiser les vérifications, prolonger son expiration, effectuer les vérifications ni envoyer d'e-mail. Nécessite le privilège `write:sessions` (une clé API restreinte nécessite un accès en écriture aux décisions) et une session au statut `Approved`, `Declined`, `In Review`, `Kyc Expired` ou `Abandoned`. Le serveur valide les étapes de workflow sélectionnées et génère son modèle traduit fixe avec l'expéditeur vérifié en marque blanche et l'image de marque applicables. La requête ne peut pas définir d'objet, de corps de message ou d'URL d'action.\n\n`email_address` est facultatif. Sans ce paramètre, l'e-mail est envoyé à l'adresse propre de la personne : celle qu'elle a vérifiée lors d'une étape de vérification d'e-mail du flux, ou à défaut celle fournie dans `contact_details` lors de la création de la session. Une adresse que vous transmettez prévaut (`recipient_source: request`). Lorsqu'aucune adresse n'est connue et que vous n'en transmettez aucune, `recipient` et `preview_token` sont des chaînes vides et aucun e-mail ne peut être envoyé.\n\nLa réponse inclut le destinataire et sa provenance, l'expéditeur, l'objet, le HTML, la langue, les étapes résolues, l'information indiquant si la confirmation entraîne l'envoi de l'e-mail (`will_be_sent`, `not_sent_reason`) et un `preview_token` signé. `requires_user_action` vaut `false` lorsque chaque étape sélectionnée s'exécute sans l'intervention de la personne : la nouvelle soumission se termine alors d'elle-même et aucun e-mail n'est envoyé (`not_sent_reason: no_user_action`).\n\nCet aperçu ne réserve pas l'état de la session et n'autorise pas l'envoi. Après l'avoir examiné, appelez [Update Session Status](/fr/sessions-api/update-status) avec `new_status: Resubmitted`, les mêmes `nodes_to_resubmit` et `email_language` que ceux prévisualisés, `send_email: true`, `email_address` défini sur `recipient` et `email_preview_token` défini sur `preview_token`. Le reçu expire après 15 minutes. Lorsqu'un reçu est fourni, toute modification des entrées, du contenu du message, de l'expéditeur ou de l'état de la session renvoie un code `409` avant toute mutation ou tout envoi. Les intégrations existantes peuvent omettre le reçu. Régénérez l'aperçu après un conflit. Traitez la réponse comme un contenu de vérification sensible ; les réponses utilisent `Cache-Control: no-store`. Restituez le HTML dans un cadre sandboxé, jamais directement dans le DOM de votre application.",
        "operationId": "post_v3_session_resubmission_preview",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "preview_resubmission",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification à mettre à jour. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB) — le service résout l'identifiant pour les deux types de session.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nodes_to_resubmit": {
                    "type": "array",
                    "description": "Étapes à prévisualiser, en utilisant les mêmes règles de validation, de sélection et d'ordonnancement du workflow qu'une nouvelle soumission. Omettez ce paramètre pour sélectionner automatiquement les tentatives enregistrées nécessitant une nouvelle soumission.",
                    "items": {
                      "type": "object",
                      "required": [
                        "node_id",
                        "feature"
                      ],
                      "properties": {
                        "node_id": {
                          "type": "string",
                          "description": "Identifiant du nœud tel qu'il apparaît dans la définition du workflow de la session (par exemple `feature_ocr`, `feature_liveness`).",
                          "example": "feature_ocr"
                        },
                        "feature": {
                          "type": "string",
                          "description": "Type de fonctionnalité du nœud. Les alias `ID_VERIFICATION`, `POA`, `PHONE` et `EMAIL` sont normalisés côté serveur en `OCR`, `PROOF_OF_ADDRESS`, `PHONE_VERIFICATION` et `EMAIL_VERIFICATION`. `KYB_REGISTRY`, `KYB_KEY_PEOPLE` et `KYB` passent la validation du schéma mais sont toujours rejetés avec l'erreur de règle métier `400` montrée dans les exemples.",
                          "enum": [
                            "OCR",
                            "OCR_BACK",
                            "NFC",
                            "AML",
                            "FACE",
                            "LIVENESS",
                            "FACE_MATCH",
                            "IP_ANALYSIS",
                            "AGE_ESTIMATION",
                            "PROOF_OF_ADDRESS",
                            "PHONE_VERIFICATION",
                            "EMAIL_VERIFICATION",
                            "FACE_SEARCH",
                            "DATABASE_VALIDATION",
                            "QUESTIONNAIRE",
                            "DOCUMENT_AI",
                            "KYB_DOCUMENTS",
                            "ID_VERIFICATION",
                            "POA",
                            "PHONE",
                            "EMAIL",
                            "KYB_REGISTRY",
                            "KYB_KEY_PEOPLE",
                            "KYB",
                            "GEOLOCATION"
                          ],
                          "example": "OCR"
                        }
                      }
                    }
                  },
                  "email_address": {
                    "type": "string",
                    "format": "email",
                    "description": "Optionnel. Envoie l'e-mail à cette adresse au lieu de celle de la personne. Sans cela, le destinataire est l'adresse vérifiée par la personne dans le workflow, sinon celle indiquée dans `contact_details`. Aucun e-mail n'est envoyé par cet appel.",
                    "example": "user@example.com"
                  },
                  "email_language": {
                    "type": "string",
                    "description": "Langue de l'e-mail de notification. Accepte n'importe quelle chaîne au niveau du schéma ; les codes non pris en charge basculent silencieusement sur l'anglais (`en`).",
                    "default": "en",
                    "example": "en"
                  }
                }
              },
              "examples": {
                "Person's Own Address": {
                  "summary": "Prévisualiser une nouvelle soumission de justificatif de domicile pour l'adresse propre de la personne",
                  "value": {
                    "nodes_to_resubmit": [
                      {
                        "node_id": "feature_poa_1",
                        "feature": "POA"
                      }
                    ],
                    "email_language": "en"
                  }
                },
                "Named Recipient": {
                  "summary": "Prévisualiser l'e-mail pour une adresse que vous indiquez",
                  "value": {
                    "nodes_to_resubmit": [
                      {
                        "node_id": "feature_ocr",
                        "feature": "OCR"
                      }
                    ],
                    "email_address": "person@example.com",
                    "email_language": "en"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Prévisualisation uniquement. La session reste inchangée et aucun e-mail n'est envoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "recipient",
                    "recipient_source",
                    "sender",
                    "sender_name",
                    "sender_email",
                    "sender_kind",
                    "subject",
                    "html",
                    "text",
                    "language",
                    "will_be_sent",
                    "not_sent_reason",
                    "preview_token",
                    "nodes_to_resubmit",
                    "requires_user_action"
                  ],
                  "properties": {
                    "recipient": {
                      "type": "string",
                      "description": "L'adresse à laquelle l'e-mail est envoyé. Une chaîne vide lorsqu'aucune adresse n'est connue pour la personne : aucun e-mail ne peut alors être envoyé et `preview_token` est également vide. Transmettez-la en tant que `email_address` lors de la confirmation.",
                      "example": "person@example.com"
                    },
                    "recipient_source": {
                      "type": "string",
                      "enum": [
                        "email_verification",
                        "contact_details",
                        "request",
                        ""
                      ],
                      "description": "Provenance de `recipient`. `request` : l'`email_address` transmise. `email_verification` : l'adresse vérifiée par la personne lors d'une étape de vérification de l'e-mail du flux. `contact_details` : l'adresse fournie dans `contact_details` lors de la création de la session. Une chaîne vide lorsqu'il n'y a pas d'adresse.",
                      "example": "email_verification"
                    },
                    "sender": {
                      "type": "string",
                      "description": "L'en-tête `From` avec lequel l'e-mail est envoyé.",
                      "example": "Example App <no-reply@mail.example.com>"
                    },
                    "sender_name": {
                      "type": "string",
                      "description": "La partie nom d'affichage de `sender`.",
                      "example": "Example App"
                    },
                    "sender_email": {
                      "type": "string",
                      "format": "email",
                      "description": "La partie adresse de `sender`.",
                      "example": "no-reply@mail.example.com"
                    },
                    "sender_kind": {
                      "type": "string",
                      "enum": [
                        "customer",
                        "didit"
                      ],
                      "description": "`customer` : l'e-mail est envoyé depuis le domaine d'expéditeur vérifié de votre application (marque blanche). `didit` : il est envoyé depuis le propre expéditeur de Didit.",
                      "example": "customer"
                    },
                    "subject": {
                      "type": "string",
                      "description": "La ligne d'objet exactement telle qu'elle est envoyée.",
                      "example": "Action Required: Complete your verification in Example App"
                    },
                    "html": {
                      "type": "string",
                      "description": "Le HTML de l'e-mail exactement tel qu'il est envoyé, avec son logo intégré sous forme de data URL. Affichez-le dans un cadre sandboxé, jamais directement dans le DOM de votre application.",
                      "example": "<!DOCTYPE html><html><body>...</body></html>"
                    },
                    "text": {
                      "type": "string",
                      "description": "Le texte brut de l'e-mail, tel qu'il apparaît dans le fil Messages de la personne, pour un aperçu compact (le HTML reste l'e-mail que la personne reçoit).",
                      "example": "Almost there\n\nSome steps need to be completed again.\nHere’s what to fix:\n\nhttps://verify.didit.me/session/abc123"
                    },
                    "language": {
                      "type": "string",
                      "description": "La langue dans laquelle l'e-mail est rédigé. Anglais (`en`) lorsque le `email_language` demandé n'est pas proposé.",
                      "example": "en"
                    },
                    "will_be_sent": {
                      "type": "boolean",
                      "description": "Indique si la confirmation de la modification avec `send_email: true` envoie cet e-mail. `false` lorsque `not_sent_reason` est défini.",
                      "example": true
                    },
                    "not_sent_reason": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "no_user_action",
                        "no_recipient",
                        "sandbox",
                        null
                      ],
                      "description": "Raison pour laquelle la confirmation n'enverrait aucun e-mail, ou `null` lorsqu'il sera envoyé. `no_user_action` : chaque étape sélectionnée s'exécute sans intervention de la personne, la nouvelle soumission se termine donc d'elle-même et aucun e-mail n'est envoyé. `no_recipient` : aucune adresse n'est connue pour la personne et vous n'en avez transmis aucune. `sandbox` : une session sandbox dont le destinataire n'a pas activé la réception d'e-mails en sandbox, l'envoi est donc seulement simulé.",
                      "example": null
                    },
                    "nodes_to_resubmit": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "node_id",
                          "feature"
                        ],
                        "properties": {
                          "node_id": {
                            "type": "string",
                            "description": "Identifiant du nœud tel qu'il apparaît dans la définition du workflow de la session (par exemple `feature_ocr`, `feature_liveness`).",
                            "example": "feature_ocr"
                          },
                          "feature": {
                            "type": "string",
                            "description": "Type de fonctionnalité du nœud. Les alias `ID_VERIFICATION`, `POA`, `PHONE` et `EMAIL` sont normalisés côté serveur en `OCR`, `PROOF_OF_ADDRESS`, `PHONE_VERIFICATION` et `EMAIL_VERIFICATION`. `KYB_REGISTRY`, `KYB_KEY_PEOPLE` et `KYB` passent la validation du schéma mais sont toujours rejetés avec l'erreur de règle métier `400` montrée dans les exemples.",
                            "enum": [
                              "OCR",
                              "OCR_BACK",
                              "NFC",
                              "AML",
                              "FACE",
                              "LIVENESS",
                              "FACE_MATCH",
                              "IP_ANALYSIS",
                              "AGE_ESTIMATION",
                              "PROOF_OF_ADDRESS",
                              "PHONE_VERIFICATION",
                              "EMAIL_VERIFICATION",
                              "FACE_SEARCH",
                              "DATABASE_VALIDATION",
                              "QUESTIONNAIRE",
                              "DOCUMENT_AI",
                              "KYB_DOCUMENTS",
                              "ID_VERIFICATION",
                              "POA",
                              "PHONE",
                              "EMAIL",
                              "KYB_REGISTRY",
                              "KYB_KEY_PEOPLE",
                              "KYB",
                              "GEOLOCATION"
                            ],
                            "example": "OCR"
                          }
                        }
                      }
                    },
                    "requires_user_action": {
                      "type": "boolean",
                      "description": "Indique si au moins un contrôle sélectionné nécessite une interaction de l'utilisateur. Cela ne présage pas du résultat final du workflow."
                    },
                    "preview_token": {
                      "type": "string",
                      "description": "Récépissé signé pour cet e-mail exact, valide pendant 15 minutes. Transmettez-le en tant que `email_preview_token` à [Mettre à jour le statut de la session](/fr/sessions-api/update-status). Une chaîne vide lorsqu'il n'y a aucun destinataire.",
                      "example": "eyJkaWdlc3QiOiI0ZjJhIn0:1uExAm:Pl3x4mpleS1gnatureValue000000000000000"
                    }
                  }
                },
                "examples": {
                  "Will Be Sent": {
                    "summary": "Destinataire par défaut : l'adresse vérifiée dans le flux",
                    "value": {
                      "recipient": "person@example.com",
                      "recipient_source": "email_verification",
                      "sender": "Example App <no-reply@mail.example.com>",
                      "sender_name": "Example App",
                      "sender_email": "no-reply@mail.example.com",
                      "sender_kind": "customer",
                      "subject": "Action Required: Complete your verification in Example App",
                      "html": "<!DOCTYPE html><html><body>...</body></html>",
                      "language": "en",
                      "will_be_sent": true,
                      "not_sent_reason": null,
                      "nodes_to_resubmit": [
                        {
                          "node_id": "feature_poa_1",
                          "feature": "PROOF_OF_ADDRESS"
                        }
                      ],
                      "requires_user_action": true,
                      "preview_token": "eyJkaWdlc3QiOiI0ZjJhIn0:1uExAm:Pl3x4mpleS1gnatureValue000000000000000"
                    }
                  },
                  "No User Action": {
                    "summary": "Seules les étapes backend sont sélectionnées, aucun e-mail n'est donc envoyé",
                    "value": {
                      "recipient": "person@example.com",
                      "recipient_source": "contact_details",
                      "sender": "Example App <no-reply@mail.example.com>",
                      "sender_name": "Example App",
                      "sender_email": "no-reply@mail.example.com",
                      "sender_kind": "customer",
                      "subject": "Action Required: Complete your verification in Example App",
                      "html": "<!DOCTYPE html><html><body>...</body></html>",
                      "language": "en",
                      "will_be_sent": false,
                      "not_sent_reason": "no_user_action",
                      "nodes_to_resubmit": [
                        {
                          "node_id": "feature_aml",
                          "feature": "AML"
                        }
                      ],
                      "requires_user_action": false,
                      "preview_token": "eyJkaWdlc3QiOiI0ZjJhIn0:1uExAm:Pl3x4mpleS1gnatureValue000000000000000"
                    }
                  }
                }
              }
            },
            "headers": {
              "Cache-Control": {
                "description": "Toujours `no-store` : l'aperçu contient du contenu de vérification et ne doit pas être mis en cache.",
                "schema": {
                  "type": "string",
                  "example": "no-store"
                }
              }
            }
          },
          "400": {
            "description": "La session n'est pas dans un statut accepté par cet endpoint, elle est déjà `Resubmitted`, les étapes sélectionnées ne peuvent pas être soumises à nouveau, ou un champ est invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Wrong Current Status": {
                    "summary": "La session n'est pas dans un statut accepté par cet endpoint",
                    "value": {
                      "detail": "Only sessions with status Approved, Declined, In Review, Kyc Expired, Abandoned, Resubmitted can be updated. Current status: In Progress"
                    }
                  },
                  "Already Resubmitted": {
                    "summary": "La session est déjà Resubmitted",
                    "value": [
                      "The new status is the same as the current status."
                    ]
                  },
                  "Nothing To Resubmit": {
                    "summary": "La sélection automatique n'a trouvé aucune étape nécessitant une nouvelle soumission",
                    "value": {
                      "nodes_to_resubmit": "No features found that need resubmission. All features are already approved."
                    }
                  },
                  "Invalid Email": {
                    "summary": "email_address n'est pas une adresse e-mail",
                    "value": {
                      "email_address": [
                        "Enter a valid email address."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API Key": {
                    "summary": "Clé API restreinte ayant dépassé sa date d'expiration",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, appelant sans le privilège `write:sessions`, clé API avec restriction de portée ne disposant pas de l'accès requis par cet endpoint, ou un `session_id` qui appartient à une autre application.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'appelant n'a pas write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped Key Without Access": {
                    "summary": "Clé API restreinte sans cet accès",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session KYC ou KYB avec ce `session_id` n'existe.",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "session_id inconnu",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Les étapes à soumettre de nouveau s'exécutent toutes exclusivement côté backend (AML, DATABASE_VALIDATION, IP_ANALYSIS), et la session a déjà été soumise à nouveau pour des étapes exclusivement backend au cours des 30 dernières secondes ; Update Session Status refuserait donc la nouvelle soumission. Réessayez après le délai indiqué dans `Retry-After`.",
            "content": {
              "application/json": {
                "examples": {
                  "Backend-only resubmit throttled": {
                    "value": {
                      "detail": "This session was already resubmitted for backend-only features within the last 30 seconds; repeating it cannot change the outcome. Wait before resubmitting again."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.preview_resubmission(\n    \"11111111-2222-3333-4444-555555555555\",\n    nodes_to_resubmit=[{\n        \"node_id\": \"feature_poa_1\",\n        \"feature\": \"POA\",\n    }],\n    email_language=\"en\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.previewResubmission(\"11111111-2222-3333-4444-555555555555\", {\n  nodes_to_resubmit: [{\n    node_id: \"feature_poa_1\",\n    feature: \"POA\",\n  }],\n  email_language: \"en\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.PreviewResubmission(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsPreviewResubmissionParams{\n\tNodesToResubmit: didit.Some([]didit.SessionsPreviewResubmissionParamsNodesToResubmit{{\n\t\tNodeID:  \"feature_poa_1\",\n\t\tFeature: \"POA\",\n\t}}),\n\tEmailLanguage: didit.String(\"en\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.SessionsPreviewResubmissionParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().previewResubmission(\"11111111-2222-3333-4444-555555555555\", SessionsPreviewResubmissionParams.builder()\n        .nodesToResubmit(List.of(SessionsPreviewResubmissionParams.NodesToResubmit.builder()\n                .nodeId(\"feature_poa_1\")\n                .feature(SessionsPreviewResubmissionParams.NodesToResubmit.Feature.of(\"POA\"))\n                .build()))\n        .emailLanguage(\"en\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->previewResubmission('11111111-2222-3333-4444-555555555555', [\n    'nodes_to_resubmit' => [[\n        'node_id' => 'feature_poa_1',\n        'feature' => 'POA',\n    ]],\n    'email_language' => 'en',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.preview_resubmission(\n  \"11111111-2222-3333-4444-555555555555\",\n  nodes_to_resubmit: [{\n    node_id: \"feature_poa_1\",\n    feature: \"POA\",\n  }],\n  email_language: \"en\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.PreviewResubmissionAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsPreviewResubmissionParams\n{\n    NodesToResubmit = new SessionsPreviewResubmissionParamsNodesToResubmit[]\n    {\n        new()\n        {\n            NodeId = \"feature_poa_1\",\n            Feature = \"POA\",\n        },\n    },\n    EmailLanguage = \"en\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/routing-rules/{record_uuid}/": {
      "get": {
        "summary": "Récupérer la règle de routage",
        "description": "Nécessite `read:cases` pour l'application demandée.",
        "operationId": "retrieve_case_routing_rules",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "retrieve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "record_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseRoutingRule"
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          },
          "404": {
            "description": "Enregistrement introuvable dans cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.routing_rules.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.routingRules.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RoutingRules.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().routingRules().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->routingRules->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.routing_rules.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RoutingRules.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour la règle de routage",
        "description": "Nécessite `write:cases` pour l'application demandée.",
        "operationId": "update_case_routing_rules",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "update",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "record_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseRoutingRule"
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          },
          "404": {
            "description": "Enregistrement introuvable dans cette application."
          },
          "409": {
            "description": "La règle de routage a été modifiée depuis expected_version. Examinez la règle la plus récente avant de réessayer."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseRoutingRuleUpdate"
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.routing_rules.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    name=\"your-name\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.routingRules.update(\"11111111-2222-3333-4444-555555555555\", {\n  name: \"your-name\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RoutingRules.Update(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CaseRoutingRuleUpdate{\n\tName: didit.String(\"your-name\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CaseRoutingRuleUpdate;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().routingRules().update(\"11111111-2222-3333-4444-555555555555\", CaseRoutingRuleUpdate.builder()\n        .name(\"your-name\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->routingRules->update('11111111-2222-3333-4444-555555555555', [\n    'name' => 'your-name',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.routing_rules.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  name: \"your-name\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RoutingRules.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", new CaseRoutingRuleUpdate\n{\n    Name = \"your-name\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/case-requests/{request_uuid}/": {
      "get": {
        "operationId": "case_requests_retrieve",
        "x-didit-sdk": {
          "resource": "case_requests",
          "method": "retrieve",
          "auth": "device_token",
          "server": false
        },
        "parameters": [
          {
            "in": "path",
            "name": "request_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerMessagingCaseRequestPublic"
                }
              }
            },
            "description": ""
          },
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          }
        },
        "security": [
          {
            "CaseRequestToken": []
          }
        ],
        "description": "Accédez à une requête client à l'aide de son token spécifique à la requête. Aucune conclusion privée du dossier, donnée d'identité d'origine ou adresse de destinataire n'est renvoyée. Les requêtes nécessitant une action expirent après sept jours. Une annulation ou la résolution du dossier invalide le lien. Les réponses sont immuables et restent des éléments de preuve pour l'évaluation du réviseur ; elles n'approuvent ni ne mettent jamais à jour une vérification source."
      },
      "post": {
        "operationId": "case_requests_create",
        "x-didit-sdk": {
          "resource": "case_requests",
          "method": "respond",
          "auth": "device_token",
          "server": false
        },
        "parameters": [
          {
            "in": "path",
            "name": "request_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMessagingCaseCustomerResponseRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMessagingCaseCustomerResponseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerMessagingCaseCustomerResponseResult"
                }
              }
            },
            "description": ""
          },
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          },
          "400": {
            "description": "Entrées non valides, finalité non prise en charge, contact vérifié indisponible ou réponse immuable déjà existante."
          },
          "409": {
            "description": "L'aperçu a changé ou a expiré. Générez à nouveau l'aperçu avant de confirmer."
          }
        },
        "security": [
          {
            "CaseRequestToken": []
          }
        ],
        "description": "Accédez à une requête client à l'aide de son token spécifique à la requête. Aucune conclusion privée du dossier, donnée d'identité d'origine ou adresse de destinataire n'est renvoyée. Les requêtes nécessitant une action expirent après sept jours. Une annulation ou la résolution du dossier invalide le lien. Les réponses sont immuables et restent des éléments de preuve pour l'évaluation du réviseur ; elles n'approuvent ni ne mettent jamais à jour une vérification source."
      }
    },
    "/v3/fraud/checks/plan/": {
      "post": {
        "operationId": "plan_create",
        "x-didit-sdk": {
          "resource": "fraud_checks",
          "method": "plan",
          "auth": "api_key",
          "server": true
        },
        "description": "Valider les vérifications sélectionnées et estimer leur prix sans exécuter les vérifications, créer une session ni facturer.",
        "summary": "Planifier une vérification de fraude",
        "tags": [
          "Fraud Check"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/FraudCheckRequestRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FraudCheckRequestRequest"
              },
              "example": {
                "client_reference": "review-attempt-001",
                "subject": {
                  "identifiers": [
                    {
                      "type": "email",
                      "value": "applicant@example.com"
                    }
                  ],
                  "attributes": {
                    "first_name": "Alex",
                    "last_name": "Example"
                  }
                },
                "checks": {
                  "include": [
                    "networks_same_org",
                    "networks_cross_org",
                    "email_risk"
                  ]
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/FraudCheckRequestRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FraudCheckPlan"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FraudBadRequestErrorMessage"
                }
              }
            },
            "description": ""
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.fraud_checks.plan(\n    client_reference=\"review-attempt-001\",\n    subject={\n        \"identifiers\": [{\n            \"type\": \"email\",\n            \"value\": \"applicant@example.com\",\n        }],\n        \"attributes\": {\n            \"first_name\": \"Alex\",\n            \"last_name\": \"Example\",\n        },\n    },\n    checks={\n        \"include\": [\"networks_same_org\", \"networks_cross_org\", \"email_risk\"],\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.fraudChecks.plan({\n  client_reference: \"review-attempt-001\",\n  subject: {\n    identifiers: [{\n      type: \"email\",\n      value: \"applicant@example.com\",\n    }],\n    attributes: {\n      first_name: \"Alex\",\n      last_name: \"Example\",\n    },\n  },\n  checks: {\n    include: [\"networks_same_org\", \"networks_cross_org\", \"email_risk\"],\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.FraudChecks.Plan(ctx, didit.FraudCheckRequestRequest{\n\tClientReference: didit.String(\"review-attempt-001\"),\n\tSubject: didit.FraudCheckSubjectRequest{\n\t\tIdentifiers: []didit.FraudCheckIdentifierRequest{{\n\t\t\tType:  didit.FraudTypeEnum(\"email\"),\n\t\t\tValue: \"applicant@example.com\",\n\t\t}},\n\t\tAttributes: didit.Some(didit.FraudCheckAttributesRequest{\n\t\t\tFirstName: didit.String(\"Alex\"),\n\t\t\tLastName:  didit.String(\"Example\"),\n\t\t}),\n\t},\n\tChecks: didit.Some(didit.FraudCheckModuleSelectionRequest{\n\t\tInclude: didit.Some([]didit.FraudExcludeEnum{didit.FraudExcludeEnum(\"networks_same_org\"), didit.FraudExcludeEnum(\"networks_cross_org\"), didit.FraudExcludeEnum(\"email_risk\")}),\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.FraudCheckAttributesRequest;\nimport me.didit.types.FraudCheckIdentifierRequest;\nimport me.didit.types.FraudCheckModuleSelectionRequest;\nimport me.didit.types.FraudCheckRequestRequest;\nimport me.didit.types.FraudCheckSubjectRequest;\nimport me.didit.types.FraudExcludeEnum;\nimport me.didit.types.FraudTypeEnum;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.fraudChecks().plan(FraudCheckRequestRequest.builder()\n        .clientReference(\"review-attempt-001\")\n        .subject(FraudCheckSubjectRequest.builder()\n                .identifiers(List.of(FraudCheckIdentifierRequest.builder()\n                        .type(FraudTypeEnum.of(\"email\"))\n                        .value(\"applicant@example.com\")\n                        .build()))\n                .attributes(FraudCheckAttributesRequest.builder()\n                        .firstName(\"Alex\")\n                        .lastName(\"Example\")\n                        .build())\n                .build())\n        .checks(FraudCheckModuleSelectionRequest.builder()\n                .include(List.of(FraudExcludeEnum.of(\"networks_same_org\"), FraudExcludeEnum.of(\"networks_cross_org\"), FraudExcludeEnum.of(\"email_risk\")))\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->fraudChecks->plan([\n    'client_reference' => 'review-attempt-001',\n    'subject' => [\n        'identifiers' => [[\n            'type' => 'email',\n            'value' => 'applicant@example.com',\n        ]],\n        'attributes' => [\n            'first_name' => 'Alex',\n            'last_name' => 'Example',\n        ],\n    ],\n    'checks' => [\n        'include' => ['networks_same_org', 'networks_cross_org', 'email_risk'],\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.fraud_checks.plan(\n  client_reference: \"review-attempt-001\",\n  subject: {\n    identifiers: [{\n      type: \"email\",\n      value: \"applicant@example.com\",\n    }],\n    attributes: {\n      first_name: \"Alex\",\n      last_name: \"Example\",\n    },\n  },\n  checks: {\n    include: [\"networks_same_org\", \"networks_cross_org\", \"email_risk\"],\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.FraudChecks.PlanAsync(new FraudCheckRequestRequest\n{\n    ClientReference = \"review-attempt-001\",\n    Subject = new()\n    {\n        Identifiers = new FraudCheckIdentifierRequest[]\n        {\n            new()\n            {\n                Type = \"email\",\n                Value = \"applicant@example.com\",\n            },\n        },\n        Attributes = new FraudCheckAttributesRequest\n        {\n            FirstName = \"Alex\",\n            LastName = \"Example\",\n        },\n    },\n    Checks = new FraudCheckModuleSelectionRequest\n    {\n        Include = new FraudExcludeEnum[] { \"networks_same_org\", \"networks_cross_org\", \"email_risk\" },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/routing-rules/": {
      "get": {
        "summary": "Lister les règles de routage",
        "description": "Nécessite `list:cases` pour l'application demandée.",
        "operationId": "list_case_routing_rules",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaseRoutingRule"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Nombre de correspondances, plafonné à 100. Suivez next pour continuer au-delà du plafond."
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.routing_rules.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.routingRules.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.RoutingRules.ListAutoPaging(ctx, didit.CasesRoutingRulesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().routingRules().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->routingRules->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.routing_rules.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.RoutingRules.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "summary": "Créer une règle de routage",
        "description": "Nécessite `write:cases` pour l'application demandée. Définissez publish=false pour créer un brouillon non publié ; Publish crée sa première version en production. Abandonner un brouillon qui n'a jamais été publié le supprime.",
        "operationId": "create_case_routing_rules",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "responses": {
          "201": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseRoutingRule"
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseRoutingRuleCreate"
              },
              "example": {
                "name": "AML screening alerts",
                "conditions": [
                  {
                    "field": "source",
                    "operator": "equals",
                    "value": "AML_SCREENING"
                  }
                ],
                "blueprint": "b1de0000-0000-4000-8000-000000000002"
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.routing_rules.create(\n    name=\"AML screening alerts\",\n    conditions=[{\n        \"field\": \"source\",\n        \"operator\": \"equals\",\n        \"value\": \"AML_SCREENING\",\n    }],\n    blueprint=\"b1de0000-0000-4000-8000-000000000002\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.routingRules.create({\n  name: \"AML screening alerts\",\n  conditions: [{\n    field: \"source\",\n    operator: \"equals\",\n    value: \"AML_SCREENING\",\n  }],\n  blueprint: \"b1de0000-0000-4000-8000-000000000002\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RoutingRules.Create(ctx, didit.CaseRoutingRuleCreate{\n\tName: \"AML screening alerts\",\n\tConditions: []didit.CaseRoutingConditionParam{{\n\t\tField:    \"source\",\n\t\tOperator: \"equals\",\n\t\tValue:    \"AML_SCREENING\",\n\t}},\n\tBlueprint: \"b1de0000-0000-4000-8000-000000000002\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.CaseRoutingCondition;\nimport me.didit.types.CaseRoutingRuleCreate;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().routingRules().create(CaseRoutingRuleCreate.builder()\n        .name(\"AML screening alerts\")\n        .conditions(List.of(CaseRoutingCondition.builder()\n                .field(CaseRoutingCondition.Field.of(\"source\"))\n                .operator(CaseRoutingCondition.Operator.of(\"equals\"))\n                .value(CaseRoutingCondition.Value.ofString(\"AML_SCREENING\"))\n                .build()))\n        .blueprint(\"b1de0000-0000-4000-8000-000000000002\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->routingRules->create([\n    'name' => 'AML screening alerts',\n    'conditions' => [[\n        'field' => 'source',\n        'operator' => 'equals',\n        'value' => 'AML_SCREENING',\n    ]],\n    'blueprint' => 'b1de0000-0000-4000-8000-000000000002',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.routing_rules.create(\n  name: \"AML screening alerts\",\n  conditions: [{\n    field: \"source\",\n    operator: \"equals\",\n    value: \"AML_SCREENING\",\n  }],\n  blueprint: \"b1de0000-0000-4000-8000-000000000002\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RoutingRules.CreateAsync(new CaseRoutingRuleCreate\n{\n    Name = \"AML screening alerts\",\n    Conditions = new CaseRoutingCondition[]\n    {\n        new()\n        {\n            Field = \"source\",\n            Operator = \"equals\",\n            Value = \"AML_SCREENING\",\n        },\n    },\n    Blueprint = \"b1de0000-0000-4000-8000-000000000002\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/routing-rules/{record_uuid}/publish/": {
      "post": {
        "operationId": "publish_case_routing_rule",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "publish",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "record_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Assignment"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPublicationPolicyDraftPreconditionRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPublicationPolicyDraftPreconditionRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPublicationPolicyDraftPreconditionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingPublicationCaseRoutingRule"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "L'accès au dossier est requis."
          },
          "409": {
            "description": "La version publiée ou la révision du brouillon a changé. Rechargez avant de réessayer."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.routing_rules.publish(\n    \"11111111-2222-3333-4444-555555555555\",\n    expected_version=0,\n    expected_revision=\"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.routingRules.publish(\"11111111-2222-3333-4444-555555555555\", {\n  expected_version: 0,\n  expected_revision: \"11111111-2222-3333-4444-555555555555\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RoutingRules.Publish(ctx, \"11111111-2222-3333-4444-555555555555\", didit.RoutingPublicationPolicyDraftPreconditionRequest{\n\tExpectedVersion:  0,\n\tExpectedRevision: didit.String(\"11111111-2222-3333-4444-555555555555\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.RoutingPublicationPolicyDraftPreconditionRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().routingRules().publish(\"11111111-2222-3333-4444-555555555555\", RoutingPublicationPolicyDraftPreconditionRequest.builder()\n        .expectedVersion(0L)\n        .expectedRevision(\"11111111-2222-3333-4444-555555555555\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->routingRules->publish('11111111-2222-3333-4444-555555555555', [\n    'expected_version' => 0,\n    'expected_revision' => '11111111-2222-3333-4444-555555555555',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.routing_rules.publish(\n  \"11111111-2222-3333-4444-555555555555\",\n  expected_version: 0,\n  expected_revision: \"11111111-2222-3333-4444-555555555555\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RoutingRules.PublishAsync(\"11111111-2222-3333-4444-555555555555\", new RoutingPublicationPolicyDraftPreconditionRequest\n{\n    ExpectedVersion = 0,\n    ExpectedRevision = \"11111111-2222-3333-4444-555555555555\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/blueprints/{blueprint_uuid}/publish/": {
      "post": {
        "operationId": "publish_case_blueprint",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "publish",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "blueprint_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CasePublicationPolicyDraftPreconditionRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CasePublicationPolicyDraftPreconditionRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CasePublicationPolicyDraftPreconditionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CasePublicationCaseBlueprint"
                }
              }
            },
            "description": ""
          },
          "409": {
            "description": "La version publiée ou la révision du brouillon enregistré a changé. Rechargez avant de réessayer."
          },
          "403": {
            "description": "Une autorisation requise pour le dossier est manquante."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.blueprints.publish(\n    \"11111111-2222-3333-4444-555555555555\",\n    expected_version=0,\n    expected_revision=\"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.blueprints.publish(\"11111111-2222-3333-4444-555555555555\", {\n  expected_version: 0,\n  expected_revision: \"11111111-2222-3333-4444-555555555555\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Blueprints.Publish(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CasePublicationPolicyDraftPreconditionRequest{\n\tExpectedVersion:  0,\n\tExpectedRevision: didit.String(\"11111111-2222-3333-4444-555555555555\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasePublicationPolicyDraftPreconditionRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().blueprints().publish(\"11111111-2222-3333-4444-555555555555\", CasePublicationPolicyDraftPreconditionRequest.builder()\n        .expectedVersion(0L)\n        .expectedRevision(\"11111111-2222-3333-4444-555555555555\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->blueprints->publish('11111111-2222-3333-4444-555555555555', [\n    'expected_version' => 0,\n    'expected_revision' => '11111111-2222-3333-4444-555555555555',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.blueprints.publish(\n  \"11111111-2222-3333-4444-555555555555\",\n  expected_version: 0,\n  expected_revision: \"11111111-2222-3333-4444-555555555555\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Blueprints.PublishAsync(\"11111111-2222-3333-4444-555555555555\", new CasePublicationPolicyDraftPreconditionRequest\n{\n    ExpectedVersion = 0,\n    ExpectedRevision = \"11111111-2222-3333-4444-555555555555\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/requests/preview/": {
      "post": {
        "operationId": "organization_application_cases_requests_preview_create",
        "x-didit-sdk": {
          "resource": "cases.requests",
          "method": "preview",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMessagingCaseRequestPreviewRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMessagingCaseRequestPreviewRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMessagingCaseRequestPreviewRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerMessagingCaseRequestPreviewResponse"
                }
              }
            },
            "description": ""
          },
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          },
          "400": {
            "description": "Entrées non valides, finalité non prise en charge, contact vérifié indisponible ou réponse immuable déjà existante."
          },
          "409": {
            "description": "L'aperçu a changé ou a expiré. Générez à nouveau l'aperçu avant de confirmer."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Générer l'aperçu de l'e-mail de production sans envoyer de message ni modifier le dossier. Renvoie le destinataire exact, l'expéditeur, l'objet, le corps et un preview_token signé. Envoyez les mêmes contact_id, purpose, language, request_id, expires_at et preview_token pour confirmer dans les 15 minutes.",
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.requests.preview(\n    \"11111111-2222-3333-4444-555555555555\",\n    contact_id=\"11111111-2222-3333-4444-555555555555\",\n    purpose=\"identity_document\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.requests.preview(\"11111111-2222-3333-4444-555555555555\", {\n  contact_id: \"11111111-2222-3333-4444-555555555555\",\n  purpose: \"identity_document\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Requests.Preview(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CustomerMessagingCaseRequestPreviewRequest{\n\tContactID: \"11111111-2222-3333-4444-555555555555\",\n\tPurpose:   didit.CustomerMessagingPurposeEnum(\"identity_document\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CustomerMessagingCaseRequestPreviewRequest;\nimport me.didit.types.CustomerMessagingPurposeEnum;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().requests().preview(\"11111111-2222-3333-4444-555555555555\", CustomerMessagingCaseRequestPreviewRequest.builder()\n        .contactId(\"11111111-2222-3333-4444-555555555555\")\n        .purpose(CustomerMessagingPurposeEnum.of(\"identity_document\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->requests->preview('11111111-2222-3333-4444-555555555555', [\n    'contact_id' => '11111111-2222-3333-4444-555555555555',\n    'purpose' => 'identity_document',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.requests.preview(\n  \"11111111-2222-3333-4444-555555555555\",\n  contact_id: \"11111111-2222-3333-4444-555555555555\",\n  purpose: \"identity_document\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Requests.PreviewAsync(\"11111111-2222-3333-4444-555555555555\", new CustomerMessagingCaseRequestPreviewRequest\n{\n    ContactId = \"11111111-2222-3333-4444-555555555555\",\n    Purpose = \"identity_document\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/action-receipts/": {
      "get": {
        "operationId": "action_receipts_retrieve",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "list_action_receipts",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "query",
            "name": "offset",
            "schema": {
              "type": "integer",
              "maximum": 1000000,
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseActionCaseActionReceiptPage"
                }
              }
            },
            "description": ""
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Lister les reçus d'action de sujet, du plus récent au plus ancien, avec au maximum 20 résultats par page. Utilisez next_offset pour la page suivante. Le texte de la note d'entrée n'est pas exposé dans l'historique.",
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.list_action_receipts(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.listActionReceipts(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.ListActionReceipts(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CasesListActionReceiptsParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().listActionReceipts(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->listActionReceipts('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.list_action_receipts(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.ListActionReceiptsAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/notes/{note_uuid}/": {
      "delete": {
        "operationId": "delete_network_note",
        "x-didit-sdk": {
          "resource": "networks.notes",
          "method": "delete",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "summary": "Supprimer votre note de réseau",
        "description": "Nécessite write:networks et l'auteur authentifié de la note. La suppression est irréversible. Les données du compte connecté et de vérification ne sont pas affectées.",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du réseau."
          },
          {
            "name": "note_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Token d'accès de l'utilisateur de la Console sous la forme Bearer <token>."
          }
        ],
        "responses": {
          "204": {
            "description": "Note supprimée."
          },
          "401": {
            "description": "L'authentification est requise."
          },
          "403": {
            "description": "Autorisation ou accès à Networks manquant."
          },
          "404": {
            "description": "Le réseau ou la note n'est pas visible pour cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\n# Also needs a console user's access token.\nclient = Didit()\n\nclient.networks.notes.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"11111111-2222-3333-4444-555555555555\",\n    extra_headers={\"Authorization\": \"Bearer YOUR_CONSOLE_USER_TOKEN\"},\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nconst didit = new Didit({\n  fetch: (url, init) => {\n    const headers = new Headers(init?.headers);\n    headers.set(\"Authorization\", \"Bearer YOUR_CONSOLE_USER_TOKEN\");\n    return fetch(url, { ...init, headers });\n  },\n});\n\nawait didit.networks.notes.delete(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nclient := didit.NewClient()\n\nif err := client.Networks.Notes.Delete(ctx, \"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\", didit.NetworksNotesDeleteParams{\n\tAuthorization: \"Bearer YOUR_CONSOLE_USER_TOKEN\",\n}); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.core.RequestOptions;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nDidit client = new Didit();\n\nclient.networks().notes().delete(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\", RequestOptions.builder()\n        .header(\"Authorization\", \"Bearer YOUR_CONSOLE_USER_TOKEN\")\n        .build());"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\n$didit = new DiditClient();\n\n$didit->networks->notes->delete('11111111-2222-3333-4444-555555555555', '11111111-2222-3333-4444-555555555555', [\n    'authorization' => 'Bearer YOUR_CONSOLE_USER_TOKEN',\n]);"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\n# Also needs a console user's access token.\ndidit = Didit::Client.new\n\ndidit.networks.notes.delete(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n  request_options: { extra_headers: { \"Authorization\" => \"Bearer YOUR_CONSOLE_USER_TOKEN\" } }\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nusing var client = new DiditClient();\n\nawait client.Networks.Notes.DeleteAsync(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\", requestOptions: new RequestOptions\n{\n    Headers = new Dictionary<string, string>\n    {\n        [\"Authorization\"] = \"Bearer YOUR_CONSOLE_USER_TOKEN\",\n    },\n});"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/action-receipts/{receipt_uuid}/retry/": {
      "post": {
        "operationId": "action_receipts_retry_create",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "retry_action_receipt",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "receipt_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseActionCaseActionReceipt"
                }
              }
            },
            "description": ""
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Réessayer uniquement cette action de sujet ayant échoué à l'aide de ses entrées enregistrées. L'autorisation d'écriture actuelle est vérifiée. Les actions appliquées renvoient leur reçu sans être exécutées à nouveau. La clôture du dossier est indépendante.",
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.retry_action_receipt(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.retryActionReceipt(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RetryActionReceipt(ctx, \"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().retryActionReceipt(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->retryActionReceipt('11111111-2222-3333-4444-555555555555', '11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.retry_action_receipt(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RetryActionReceiptAsync(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/blueprints/{blueprint_uuid}/draft/": {
      "get": {
        "operationId": "get_case_blueprint_draft",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "retrieve_draft",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "blueprint_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CasePublicationPolicyDraftResponse"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "Une autorisation requise pour le dossier est manquante."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.blueprints.retrieve_draft(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.blueprints.retrieveDraft(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Blueprints.RetrieveDraft(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().blueprints().retrieveDraft(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->blueprints->retrieveDraft('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.blueprints.retrieve_draft(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Blueprints.RetrieveDraftAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "put": {
        "operationId": "save_case_blueprint_draft",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "save_draft",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "blueprint_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CasePublicationPolicyDraftWriteRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CasePublicationPolicyDraftWriteRequest"
              },
              "example": {
                "expected_version": 1,
                "expected_revision": "4e5f0000-0000-4000-8000-000000000003",
                "changes": {
                  "max_active_cases": 20
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CasePublicationPolicyDraftWriteRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CasePublicationPolicyDraft"
                }
              }
            },
            "description": ""
          },
          "409": {
            "description": "La version publiée ou la révision du brouillon enregistré a changé. Rechargez avant de réessayer."
          },
          "403": {
            "description": "Une autorisation requise pour le dossier est manquante."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.blueprints.save_draft(\n    \"11111111-2222-3333-4444-555555555555\",\n    expected_version=1,\n    expected_revision=\"4e5f0000-0000-4000-8000-000000000003\",\n    changes={\"max_active_cases\": 20},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.blueprints.saveDraft(\"11111111-2222-3333-4444-555555555555\", {\n  expected_version: 1,\n  expected_revision: \"4e5f0000-0000-4000-8000-000000000003\",\n  changes: { max_active_cases: 20 },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Blueprints.SaveDraft(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CasePublicationPolicyDraftWriteRequest{\n\tExpectedVersion:  1,\n\tExpectedRevision: didit.String(\"4e5f0000-0000-4000-8000-000000000003\"),\n\tChanges:          map[string]any{\"max_active_cases\": 20},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.CasePublicationPolicyDraftWriteRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().blueprints().saveDraft(\"11111111-2222-3333-4444-555555555555\", CasePublicationPolicyDraftWriteRequest.builder()\n        .expectedVersion(1L)\n        .expectedRevision(\"4e5f0000-0000-4000-8000-000000000003\")\n        .changes(Map.of(\"max_active_cases\", 20))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->blueprints->saveDraft('11111111-2222-3333-4444-555555555555', [\n    'expected_version' => 1,\n    'expected_revision' => '4e5f0000-0000-4000-8000-000000000003',\n    'changes' => ['max_active_cases' => 20],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.blueprints.save_draft(\n  \"11111111-2222-3333-4444-555555555555\",\n  expected_version: 1,\n  expected_revision: \"4e5f0000-0000-4000-8000-000000000003\",\n  changes: { max_active_cases: 20 }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Blueprints.SaveDraftAsync(\"11111111-2222-3333-4444-555555555555\", new CasePublicationPolicyDraftWriteRequest\n{\n    ExpectedVersion = 1,\n    ExpectedRevision = \"4e5f0000-0000-4000-8000-000000000003\",\n    Changes = new Dictionary<string, object> { [\"max_active_cases\"] = 20 },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "operationId": "discard_case_blueprint_draft",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "discard_draft",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "blueprint_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "204": {
            "description": "Aucun corps de réponse"
          },
          "409": {
            "description": "La version publiée ou la révision du brouillon enregistré a changé. Rechargez avant de réessayer."
          },
          "403": {
            "description": "Une autorisation requise pour le dossier est manquante."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CasePublicationPolicyDraftPreconditionRequest"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.cases.blueprints.discard_draft(\n    \"11111111-2222-3333-4444-555555555555\",\n    expected_version=0,\n    expected_revision=\"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.cases.blueprints.discardDraft(\"11111111-2222-3333-4444-555555555555\", {\n  expected_version: 0,\n  expected_revision: \"11111111-2222-3333-4444-555555555555\",\n});"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nif err := client.Cases.Blueprints.DiscardDraft(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CasePublicationPolicyDraftPreconditionRequest{\n\tExpectedVersion:  0,\n\tExpectedRevision: didit.String(\"11111111-2222-3333-4444-555555555555\"),\n}); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CasePublicationPolicyDraftPreconditionRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.cases().blueprints().discardDraft(\"11111111-2222-3333-4444-555555555555\", CasePublicationPolicyDraftPreconditionRequest.builder()\n        .expectedVersion(0L)\n        .expectedRevision(\"11111111-2222-3333-4444-555555555555\")\n        .build());"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->cases->blueprints->discardDraft('11111111-2222-3333-4444-555555555555', [\n    'expected_version' => 0,\n    'expected_revision' => '11111111-2222-3333-4444-555555555555',\n]);"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.blueprints.discard_draft(\n  \"11111111-2222-3333-4444-555555555555\",\n  expected_version: 0,\n  expected_revision: \"11111111-2222-3333-4444-555555555555\"\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.Cases.Blueprints.DiscardDraftAsync(\"11111111-2222-3333-4444-555555555555\", new CasePublicationPolicyDraftPreconditionRequest\n{\n    ExpectedVersion = 0,\n    ExpectedRevision = \"11111111-2222-3333-4444-555555555555\",\n});"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/teams/{record_uuid}/": {
      "get": {
        "summary": "Récupérer l'équipe d'examen",
        "description": "Nécessite `read:cases` pour l'application demandée.",
        "operationId": "retrieve_case_teams",
        "x-didit-sdk": {
          "resource": "cases.teams",
          "method": "retrieve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "record_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseReviewTeam"
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          },
          "404": {
            "description": "Enregistrement introuvable dans cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.teams.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.teams.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Teams.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().teams().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->teams->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.teams.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Teams.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour l'équipe d'examen",
        "description": "Nécessite `write:cases` pour l'application demandée.",
        "operationId": "update_case_teams",
        "x-didit-sdk": {
          "resource": "cases.teams",
          "method": "update",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "record_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseReviewTeam"
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          },
          "404": {
            "description": "Enregistrement introuvable dans cette application."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseReviewTeamUpdate"
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.teams.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    name=\"your-name\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.teams.update(\"11111111-2222-3333-4444-555555555555\", {\n  name: \"your-name\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Teams.Update(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CaseReviewTeamUpdate{\n\tName: didit.String(\"your-name\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CaseReviewTeamUpdate;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().teams().update(\"11111111-2222-3333-4444-555555555555\", CaseReviewTeamUpdate.builder()\n        .name(\"your-name\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->teams->update('11111111-2222-3333-4444-555555555555', [\n    'name' => 'your-name',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.teams.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  name: \"your-name\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Teams.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", new CaseReviewTeamUpdate\n{\n    Name = \"your-name\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/report/": {
      "get": {
        "operationId": "download_network_report",
        "x-didit-sdk": {
          "resource": "networks",
          "method": "download_report",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "summary": "Télécharger un rapport de preuves de réseau",
        "description": "Télécharger un PDF du réseau actuel de l'organisation, de ses connexions de comptes observées, des références de signaux et du statut d'examen. Nécessite read:networks. Les renseignements globaux et les notes privées d'analystes ne sont pas inclus. Chaque liste de comptes et de signaux est plafonnée à 500 entrées et le rapport indique lorsqu'elle est incomplète. La requête ne modifie pas l'état du réseau. Les erreurs sont renvoyées sous forme de JSON.",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du réseau."
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Token d'accès de l'utilisateur de la Console sous la forme Bearer <token>."
          }
        ],
        "responses": {
          "200": {
            "description": "Rapport de preuves du réseau. Cache-Control: no-store.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "L'authentification est requise."
          },
          "403": {
            "description": "Autorisation ou accès à Networks manquant."
          },
          "404": {
            "description": "Le réseau ou la note n'est pas visible pour cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\n# Also needs a console user's access token.\nclient = Didit()\n\ncontent = client.networks.download_report(\n    \"11111111-2222-3333-4444-555555555555\",\n    extra_headers={\"Authorization\": \"Bearer YOUR_CONSOLE_USER_TOKEN\"},\n)\nwith open(\"download.pdf\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nconst didit = new Didit({\n  fetch: (url, init) => {\n    const headers = new Headers(init?.headers);\n    headers.set(\"Authorization\", \"Bearer YOUR_CONSOLE_USER_TOKEN\");\n    return fetch(url, { ...init, headers });\n  },\n});\n\nconst content = await didit.networks.downloadReport(\"11111111-2222-3333-4444-555555555555\");\nawait writeFile(\"download.pdf\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nclient := didit.NewClient()\n\nresp, err := client.Networks.DownloadReport(ctx, \"11111111-2222-3333-4444-555555555555\", didit.NetworksDownloadReportParams{\n\tAuthorization: \"Bearer YOUR_CONSOLE_USER_TOKEN\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\nimport me.didit.core.RequestOptions;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nDidit client = new Didit();\n\nclient.networks().downloadReport(\"11111111-2222-3333-4444-555555555555\", RequestOptions.builder()\n        .header(\"Authorization\", \"Bearer YOUR_CONSOLE_USER_TOKEN\")\n        .build())\n        .writeTo(Path.of(\"download.pdf\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\n$didit = new DiditClient();\n\n$content = $didit->networks->downloadReport('11111111-2222-3333-4444-555555555555', [\n    'authorization' => 'Bearer YOUR_CONSOLE_USER_TOKEN',\n]);\n$content->saveTo('download.pdf');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\n# Also needs a console user's access token.\ndidit = Didit::Client.new\n\ncontent = didit.networks.download_report(\n  \"11111111-2222-3333-4444-555555555555\",\n  request_options: { extra_headers: { \"Authorization\" => \"Bearer YOUR_CONSOLE_USER_TOKEN\" } }\n)\nFile.binwrite(\"download.pdf\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nusing var client = new DiditClient();\n\nvar content = await client.Networks.DownloadReportAsync(\"11111111-2222-3333-4444-555555555555\", requestOptions: new RequestOptions\n{\n    Headers = new Dictionary<string, string>\n    {\n        [\"Authorization\"] = \"Bearer YOUR_CONSOLE_USER_TOKEN\",\n    },\n});\nawait content.SaveToAsync(\"download.pdf\");"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/notes/": {
      "get": {
        "operationId": "list_network_notes",
        "x-didit-sdk": {
          "resource": "networks.notes",
          "method": "list",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "summary": "Lister les notes de réseau privé",
        "description": "Les utilisateurs de la Console disposant de read:networks peuvent lire les notes sur un réseau visible par l'application. Les notes restent au sein de l'organisation et ne sont pas partagées avec le renseignement collectif. Les notes les plus récentes apparaissent en premier.",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du réseau."
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Token d'accès de l'utilisateur de la Console sous la forme Bearer <token>."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de notes. Le nombre est limité à 100 ; utilisez next pour continuer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NetworkNote"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "L'authentification est requise."
          },
          "403": {
            "description": "Autorisation ou accès à Networks manquant."
          },
          "404": {
            "description": "Le réseau ou la note n'est pas visible pour cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\n# Also needs a console user's access token.\nclient = Didit()\n\nfor item in client.networks.notes.list(\n    \"11111111-2222-3333-4444-555555555555\",\n    extra_headers={\"Authorization\": \"Bearer YOUR_CONSOLE_USER_TOKEN\"},\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nconst didit = new Didit({\n  fetch: (url, init) => {\n    const headers = new Headers(init?.headers);\n    headers.set(\"Authorization\", \"Bearer YOUR_CONSOLE_USER_TOKEN\");\n    return fetch(url, { ...init, headers });\n  },\n});\n\nfor await (const item of didit.networks.notes.list(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nclient := didit.NewClient()\n\niter := client.Networks.Notes.ListAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.NetworksNotesListParams{\n\tAuthorization: \"Bearer YOUR_CONSOLE_USER_TOKEN\",\n})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.core.RequestOptions;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nDidit client = new Didit();\n\nfor (var item : client.networks().notes().list(\"11111111-2222-3333-4444-555555555555\", RequestOptions.builder()\n        .header(\"Authorization\", \"Bearer YOUR_CONSOLE_USER_TOKEN\")\n        .build())) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\n$didit = new DiditClient();\n\nforeach ($didit->networks->notes->list('11111111-2222-3333-4444-555555555555', [\n    'authorization' => 'Bearer YOUR_CONSOLE_USER_TOKEN',\n]) as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\n# Also needs a console user's access token.\ndidit = Didit::Client.new\n\ndidit.networks.notes.list(\n  \"11111111-2222-3333-4444-555555555555\",\n  request_options: { extra_headers: { \"Authorization\" => \"Bearer YOUR_CONSOLE_USER_TOKEN\" } }\n).auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Networks.Notes.ListAsync(\"11111111-2222-3333-4444-555555555555\", requestOptions: new RequestOptions\n{\n    Headers = new Dictionary<string, string>\n    {\n        [\"Authorization\"] = \"Bearer YOUR_CONSOLE_USER_TOKEN\",\n    },\n}))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      },
      "post": {
        "operationId": "create_network_note",
        "x-didit-sdk": {
          "resource": "networks.notes",
          "method": "create",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Networks"
        ],
        "summary": "Ajouter une note de réseau privée",
        "description": "Nécessite un utilisateur de la console avec write:networks. L'auteur est défini à partir de l'utilisateur authentifié. Fournissez un nouvel UUID aléatoire client_reference pour chaque note ; réessayez avec le même corps et la même référence après une réponse incertaine pour éviter les doublons. Réutiliser une référence pour un autre corps, auteur ou réseau renvoie 409. Les notes suivent l'enquête qui subsiste lors de la fusion de réseaux.",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du réseau."
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Token d'accès de l'utilisateur de la Console sous la forme Bearer <token>."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "comment",
                  "client_reference"
                ],
                "properties": {
                  "comment": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "client_reference": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Note privée enregistrée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkNote"
                }
              }
            }
          },
          "200": {
            "description": "Note privée enregistrée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkNote"
                }
              }
            }
          },
          "400": {
            "description": "Note non valide ou vide."
          },
          "409": {
            "description": "La référence a déjà été utilisée pour une autre note."
          },
          "401": {
            "description": "L'authentification est requise."
          },
          "403": {
            "description": "Autorisation ou accès à Networks manquant."
          },
          "404": {
            "description": "Le réseau ou la note n'est pas visible pour cette application."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\n# Also needs a console user's access token.\nclient = Didit()\n\nresult = client.networks.notes.create(\n    \"11111111-2222-3333-4444-555555555555\",\n    comment=\"your-comment\",\n    client_reference=\"11111111-2222-3333-4444-555555555555\",\n    extra_headers={\"Authorization\": \"Bearer YOUR_CONSOLE_USER_TOKEN\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nconst didit = new Didit({\n  fetch: (url, init) => {\n    const headers = new Headers(init?.headers);\n    headers.set(\"Authorization\", \"Bearer YOUR_CONSOLE_USER_TOKEN\");\n    return fetch(url, { ...init, headers });\n  },\n});\n\nconst result = await didit.networks.notes.create(\"11111111-2222-3333-4444-555555555555\", {\n  comment: \"your-comment\",\n  client_reference: \"11111111-2222-3333-4444-555555555555\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nclient := didit.NewClient()\n\nresult, err := client.Networks.Notes.Create(ctx, \"11111111-2222-3333-4444-555555555555\", didit.NetworksNotesCreateParams{\n\tComment:         \"your-comment\",\n\tClientReference: \"11111111-2222-3333-4444-555555555555\",\n\tAuthorization:   \"Bearer YOUR_CONSOLE_USER_TOKEN\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.core.RequestOptions;\nimport me.didit.types.NetworksNotesCreateParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nDidit client = new Didit();\n\nvar result = client.networks().notes().create(\"11111111-2222-3333-4444-555555555555\", NetworksNotesCreateParams.builder()\n        .comment(\"your-comment\")\n        .clientReference(\"11111111-2222-3333-4444-555555555555\")\n        .build(), RequestOptions.builder()\n        .header(\"Authorization\", \"Bearer YOUR_CONSOLE_USER_TOKEN\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\n$didit = new DiditClient();\n\n$result = $didit->networks->notes->create('11111111-2222-3333-4444-555555555555', [\n    'comment' => 'your-comment',\n    'client_reference' => '11111111-2222-3333-4444-555555555555',\n    'authorization' => 'Bearer YOUR_CONSOLE_USER_TOKEN',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\n# Also needs a console user's access token.\ndidit = Didit::Client.new\n\nresult = didit.networks.notes.create(\n  \"11111111-2222-3333-4444-555555555555\",\n  comment: \"your-comment\",\n  client_reference: \"11111111-2222-3333-4444-555555555555\",\n  request_options: { extra_headers: { \"Authorization\" => \"Bearer YOUR_CONSOLE_USER_TOKEN\" } }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n// Also needs a console user's access token.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.Notes.CreateAsync(\"11111111-2222-3333-4444-555555555555\", new NetworksNotesCreateParams\n{\n    Comment = \"your-comment\",\n    ClientReference = \"11111111-2222-3333-4444-555555555555\",\n}, requestOptions: new RequestOptions\n{\n    Headers = new Dictionary<string, string>\n    {\n        [\"Authorization\"] = \"Bearer YOUR_CONSOLE_USER_TOKEN\",\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/routing-rules/{record_uuid}/draft/": {
      "get": {
        "operationId": "get_case_routing_rule_draft",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "retrieve_draft",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "record_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Assignment"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingPublicationPolicyDraftResponse"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "L'accès au dossier est requis."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.routing_rules.retrieve_draft(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.routingRules.retrieveDraft(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RoutingRules.RetrieveDraft(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().routingRules().retrieveDraft(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->routingRules->retrieveDraft('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.routing_rules.retrieve_draft(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RoutingRules.RetrieveDraftAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "put": {
        "operationId": "save_case_routing_rule_draft",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "save_draft",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "record_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Assignment"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPublicationPolicyDraftWriteRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPublicationPolicyDraftWriteRequest"
              },
              "example": {
                "expected_version": 1,
                "expected_revision": "4e5f0000-0000-4000-8000-000000000003",
                "changes": {
                  "priority": 10
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPublicationPolicyDraftWriteRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingPublicationPolicyDraft"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "L'accès au dossier est requis."
          },
          "409": {
            "description": "La version publiée ou la révision du brouillon a changé. Rechargez avant de réessayer."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.routing_rules.save_draft(\n    \"11111111-2222-3333-4444-555555555555\",\n    expected_version=1,\n    expected_revision=\"4e5f0000-0000-4000-8000-000000000003\",\n    changes={\"priority\": 10},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.routingRules.saveDraft(\"11111111-2222-3333-4444-555555555555\", {\n  expected_version: 1,\n  expected_revision: \"4e5f0000-0000-4000-8000-000000000003\",\n  changes: { priority: 10 },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RoutingRules.SaveDraft(ctx, \"11111111-2222-3333-4444-555555555555\", didit.RoutingPublicationPolicyDraftWriteRequest{\n\tExpectedVersion:  1,\n\tExpectedRevision: didit.String(\"4e5f0000-0000-4000-8000-000000000003\"),\n\tChanges:          map[string]any{\"priority\": 10},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.RoutingPublicationPolicyDraftWriteRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().routingRules().saveDraft(\"11111111-2222-3333-4444-555555555555\", RoutingPublicationPolicyDraftWriteRequest.builder()\n        .expectedVersion(1L)\n        .expectedRevision(\"4e5f0000-0000-4000-8000-000000000003\")\n        .changes(Map.of(\"priority\", 10))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->routingRules->saveDraft('11111111-2222-3333-4444-555555555555', [\n    'expected_version' => 1,\n    'expected_revision' => '4e5f0000-0000-4000-8000-000000000003',\n    'changes' => ['priority' => 10],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.routing_rules.save_draft(\n  \"11111111-2222-3333-4444-555555555555\",\n  expected_version: 1,\n  expected_revision: \"4e5f0000-0000-4000-8000-000000000003\",\n  changes: { priority: 10 }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RoutingRules.SaveDraftAsync(\"11111111-2222-3333-4444-555555555555\", new RoutingPublicationPolicyDraftWriteRequest\n{\n    ExpectedVersion = 1,\n    ExpectedRevision = \"4e5f0000-0000-4000-8000-000000000003\",\n    Changes = new Dictionary<string, object> { [\"priority\"] = 10 },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "operationId": "discard_case_routing_rule_draft",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "discard_draft",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "record_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Assignment"
        ],
        "responses": {
          "204": {
            "description": "Aucun corps de réponse"
          },
          "403": {
            "description": "L'accès au dossier est requis."
          },
          "409": {
            "description": "La version publiée ou la révision du brouillon a changé. Rechargez avant de réessayer."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPublicationPolicyDraftPreconditionRequest"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.cases.routing_rules.discard_draft(\n    \"11111111-2222-3333-4444-555555555555\",\n    expected_version=0,\n    expected_revision=\"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.cases.routingRules.discardDraft(\"11111111-2222-3333-4444-555555555555\", {\n  expected_version: 0,\n  expected_revision: \"11111111-2222-3333-4444-555555555555\",\n});"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nif err := client.Cases.RoutingRules.DiscardDraft(ctx, \"11111111-2222-3333-4444-555555555555\", didit.RoutingPublicationPolicyDraftPreconditionRequest{\n\tExpectedVersion:  0,\n\tExpectedRevision: didit.String(\"11111111-2222-3333-4444-555555555555\"),\n}); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.RoutingPublicationPolicyDraftPreconditionRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.cases().routingRules().discardDraft(\"11111111-2222-3333-4444-555555555555\", RoutingPublicationPolicyDraftPreconditionRequest.builder()\n        .expectedVersion(0L)\n        .expectedRevision(\"11111111-2222-3333-4444-555555555555\")\n        .build());"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->cases->routingRules->discardDraft('11111111-2222-3333-4444-555555555555', [\n    'expected_version' => 0,\n    'expected_revision' => '11111111-2222-3333-4444-555555555555',\n]);"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.routing_rules.discard_draft(\n  \"11111111-2222-3333-4444-555555555555\",\n  expected_version: 0,\n  expected_revision: \"11111111-2222-3333-4444-555555555555\"\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.Cases.RoutingRules.DiscardDraftAsync(\"11111111-2222-3333-4444-555555555555\", new RoutingPublicationPolicyDraftPreconditionRequest\n{\n    ExpectedVersion = 0,\n    ExpectedRevision = \"11111111-2222-3333-4444-555555555555\",\n});"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/duplicates/": {
      "post": {
        "operationId": "duplicates_create",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "find_duplicates",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          }
        ],
        "tags": [
          "Case Management"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CaseDuplicateCaseDuplicateQueryRequest"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseDuplicateCaseDuplicateQueryRequest"
              },
              "example": {
                "subject": {
                  "type": "user",
                  "uuid": "5b9a0000-0000-4000-8000-00000000f00d"
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CaseDuplicateCaseDuplicateQueryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseDuplicateCaseDuplicatePage"
                }
              }
            },
            "description": ""
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Passez en revue les dossiers existants pour un sujet ou un enregistrement source détenu avant la création manuelle d'un dossier. Les enquêtes ouvertes et résolues sont toutes deux renvoyées. Chaque page contient au maximum 20 dossiers ; utilisez next_offset pour demander une autre page.",
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.find_duplicates(\n    subject={\n        \"type\": \"user\",\n        \"uuid\": \"5b9a0000-0000-4000-8000-00000000f00d\",\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.findDuplicates({\n  subject: {\n    type: \"user\",\n    uuid: \"5b9a0000-0000-4000-8000-00000000f00d\",\n  },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.FindDuplicates(ctx, didit.CaseDuplicateCaseDuplicateQueryRequest{\n\tSubject: didit.Some(didit.CaseDuplicateCaseSubjectInputRequest{\n\t\tType: didit.CaseDuplicateTypeEnum(\"user\"),\n\t\tUUID: \"5b9a0000-0000-4000-8000-00000000f00d\",\n\t}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CaseDuplicateCaseDuplicateQueryRequest;\nimport me.didit.types.CaseDuplicateCaseSubjectInputRequest;\nimport me.didit.types.CaseDuplicateTypeEnum;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().findDuplicates(CaseDuplicateCaseDuplicateQueryRequest.builder()\n        .subject(CaseDuplicateCaseSubjectInputRequest.builder()\n                .type(CaseDuplicateTypeEnum.of(\"user\"))\n                .uuid(\"5b9a0000-0000-4000-8000-00000000f00d\")\n                .build())\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->findDuplicates([\n    'subject' => [\n        'type' => 'user',\n        'uuid' => '5b9a0000-0000-4000-8000-00000000f00d',\n    ],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.find_duplicates(\n  subject: {\n    type: \"user\",\n    uuid: \"5b9a0000-0000-4000-8000-00000000f00d\",\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.FindDuplicatesAsync(new CaseDuplicateCaseDuplicateQueryRequest\n{\n    Subject = new CaseDuplicateCaseSubjectInputRequest\n    {\n        Type = \"user\",\n        Uuid = \"5b9a0000-0000-4000-8000-00000000f00d\",\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/routing-rules/preview/": {
      "post": {
        "summary": "Routage du cas de test",
        "description": "Nécessite `read:cases` pour l'application demandée. Évalue les règles actuelles ou un brouillon fourni par rapport aux accès, disponibilités, compétences et capacités actuels des réviseurs. Cela n'enregistre pas le brouillon et ne réserve pas de capacité de réviseur.",
        "operationId": "preview_case_routing",
        "x-didit-sdk": {
          "resource": "cases.routing_rules",
          "method": "preview",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "responses": {
          "200": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaseRoutingPreview"
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaseRoutingPreviewRequest"
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.routing_rules.preview(\n    source=\"MANUAL\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.routingRules.preview({\n  source: \"MANUAL\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.RoutingRules.Preview(ctx, didit.CaseRoutingPreviewRequest{\n\tSource: \"MANUAL\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.CaseRoutingPreviewRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().routingRules().preview(CaseRoutingPreviewRequest.builder()\n        .source(CaseRoutingPreviewRequest.Source.of(\"MANUAL\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->routingRules->preview([\n    'source' => 'MANUAL',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.routing_rules.preview(source: \"MANUAL\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.RoutingRules.PreviewAsync(new CaseRoutingPreviewRequest\n{\n    Source = \"MANUAL\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/reviewers/": {
      "get": {
        "summary": "Lister les réviseurs éligibles pour le dossier",
        "description": "Nécessite `list:cases` pour l'application demandée.",
        "operationId": "list_case_reviewers",
        "x-didit-sdk": {
          "resource": "cases",
          "method": "list_reviewers",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Case Assignment"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "responses": {
          "200": {
            "description": "Succès",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "user_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "email": {
                            "type": "string",
                            "format": "email"
                          },
                          "name": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Entrée non valide."
          },
          "403": {
            "description": "Autorisation insuffisante."
          },
          "503": {
            "description": "Impossible de vérifier l'accès du réviseur. Réessayez plus tard."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.list_reviewers()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.listReviewers();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.ListReviewers(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().listReviewers();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->listReviewers();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.list_reviewers\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.ListReviewersAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/blueprints/{blueprint_uuid}/history/": {
      "get": {
        "operationId": "list_case_blueprint_history",
        "x-didit-sdk": {
          "resource": "cases.blueprints",
          "method": "list_history",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "blueprint_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Quel champ utiliser pour trier les résultats.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Nombre de résultats à retourner par page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "L'index initial à partir duquel renvoyer les résultats.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "tags": [
          "Case Management"
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CasePublicationPaginatedPolicyRevisionList"
                }
              }
            },
            "description": ""
          },
          "403": {
            "description": "Une autorisation requise pour le dossier est manquante."
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nfor item in client.cases.blueprints.list_history(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nfor await (const item of didit.cases.blueprints.listHistory(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\niter := client.Cases.Blueprints.ListHistoryAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.CasesBlueprintsListHistoryParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nfor (var item : client.cases().blueprints().listHistory(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\nforeach ($didit->cases->blueprints->listHistory('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.cases.blueprints.list_history(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Cases.Blueprints.ListHistoryAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/signatures/{nodeId}/documents/{documentId}/file/": {
      "get": {
        "summary": "Télécharger un document signé",
        "description": "Télécharger le PDF signé d'un document d'une étape de signature électronique. Utilisez le chemin `signed_file` de `signatures[].documents[]` dans la décision. Le PDF contient le document présenté au signataire avec les valeurs de ses champs apposées ainsi que la page de preuves (sauf si `signature_evidence_page` est désactivé). Un PDF avancé (AES) comporte également la signature PAdES avec son horodatage ; un PDF simple ne comporte aucune signature numérique, aucun cachet ni horodatage. Didit vérifie le fichier par rapport à `sha256_signed` avant de le renvoyer.\n\nFonctionne pour les sessions de vérification des utilisateurs (KYC) et de vérification d'entreprise (KYB). Nécessite `read:sessions` ; votre clé API fonctionne. Consultez le [rapport de signature électronique](/fr/core-technology/electronic-signature/report-electronic-signature#télécharger-les-documents-signés).",
        "operationId": "get_v3_session_signature_document_file",
        "x-didit-sdk": {
          "resource": "sessions.signatures",
          "method": "download_document",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "La session de vérification des utilisateurs (KYC) ou de vérification d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "description": "L'étape de signature électronique : `node_id` de l'élément dans `signatures[]`.",
            "schema": {
              "type": "string",
              "example": "feature_signature"
            }
          },
          {
            "name": "documentId",
            "in": "path",
            "required": true,
            "description": "`id` du document dans `signatures[].documents[]`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Le PDF signé.",
            "headers": {
              "Content-Disposition": {
                "description": "Pièce jointe avec le nom de fichier.",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=\"agreement-signed.pdf\""
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, ou identifiant ne pouvant pas lire cette session. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "You do not have permission to perform this action."
                }
              }
            }
          },
          "404": {
            "description": "Aucun document signé ne correspond : la session, l'étape ou le document n'existe pas, a été supprimé ou n'est pas encore signé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not signed yet": {
                    "summary": "Le signataire n'a pas signé",
                    "value": {
                      "code": "signature_not_signed",
                      "detail": "signature_not_signed"
                    }
                  },
                  "Unknown document": {
                    "summary": "Aucun document de ce type dans cette étape",
                    "value": {
                      "code": "signature_not_found",
                      "detail": "signature_not_found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Le fichier enregistré ne correspond plus à son empreinte SHA-256 enregistrée. Rien n'est renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Changed file": {
                    "summary": "Le fichier stocké ne correspond pas à son hachage",
                    "value": {
                      "code": "signature_document_changed",
                      "detail": "signature_document_changed"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.sessions.signatures.download_document(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"feature_signature\",\n    \"11111111-2222-3333-4444-555555555555\",\n)\nwith open(\"download.pdf\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.sessions.signatures.downloadDocument(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_signature\",\n  \"11111111-2222-3333-4444-555555555555\",\n);\nawait writeFile(\"download.pdf\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.Sessions.Signatures.DownloadDocument(ctx, \"11111111-2222-3333-4444-555555555555\", \"feature_signature\", \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.sessions().signatures().downloadDocument(\"11111111-2222-3333-4444-555555555555\", \"feature_signature\", \"11111111-2222-3333-4444-555555555555\")\n        .writeTo(Path.of(\"download.pdf\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->sessions->signatures->downloadDocument('11111111-2222-3333-4444-555555555555', 'feature_signature', '11111111-2222-3333-4444-555555555555');\n$content->saveTo('download.pdf');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.sessions.signatures.download_document(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_signature\",\n  \"11111111-2222-3333-4444-555555555555\"\n)\nFile.binwrite(\"download.pdf\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.Sessions.Signatures.DownloadDocumentAsync(\"11111111-2222-3333-4444-555555555555\", \"feature_signature\", \"11111111-2222-3333-4444-555555555555\");\nawait content.SaveToAsync(\"download.pdf\");"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/signatures/{nodeId}/evidence/": {
      "get": {
        "summary": "Télécharger les preuves de signature",
        "description": "Télécharger le PDF de preuves d'un signataire : le niveau et le format, le signataire, l'adresse IP, chaque document avec son SHA-256 d'origine et les valeurs des champs, ainsi que le SHA-256 de chaque fichier signé, plus, pour une signature avancée (AES), la session d'identité vérifiée, la confirmation par code, le certificat et l'horodatage. Utilisez le chemin `evidence_file` de l'élément du signataire dans `signatures[]`.\n\nTransmettez toujours `signature_id` lorsqu'une étape de Vérification d'entreprise (KYB) comporte plusieurs signataires : sans cela, la route choisit l'un des signataires de l'étape. Nécessite `read:sessions` ; votre clé API fonctionne.",
        "operationId": "get_v3_session_signature_evidence",
        "x-didit-sdk": {
          "resource": "sessions.signatures",
          "method": "download_evidence",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "La session de vérification des utilisateurs (KYC) ou de vérification d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "description": "L'étape de signature électronique : `node_id` de l'élément dans `signatures[]`.",
            "schema": {
              "type": "string",
              "example": "feature_signature"
            }
          },
          {
            "name": "signature_id",
            "in": "query",
            "required": false,
            "description": "`id` de l'élément du signataire dans `signatures[]`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Le PDF des éléments de preuve.",
            "headers": {
              "Content-Disposition": {
                "description": "Pièce jointe avec le nom de fichier.",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=\"signature-evidence.pdf\""
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, ou identifiant ne pouvant pas lire cette session. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "You do not have permission to perform this action."
                }
              }
            }
          },
          "404": {
            "description": "Aucun élément de preuve ne correspond : la session, l'étape ou le signataire n'existe pas, a été supprimé(e) ou n'a pas signé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not signed yet": {
                    "summary": "Le signataire n'a pas signé",
                    "value": {
                      "code": "signature_not_signed",
                      "detail": "signature_not_signed"
                    }
                  },
                  "Unknown signer": {
                    "summary": "Aucune signature de ce type dans cette étape",
                    "value": {
                      "code": "signature_not_found",
                      "detail": "signature_not_found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Le fichier enregistré ne correspond plus à son empreinte SHA-256 enregistrée. Rien n'est renvoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Changed file": {
                    "summary": "Le fichier stocké ne correspond pas à son hachage",
                    "value": {
                      "code": "signature_document_changed",
                      "detail": "signature_document_changed"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.sessions.signatures.download_evidence(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"feature_signature\",\n)\nwith open(\"download.pdf\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.sessions.signatures.downloadEvidence(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_signature\",\n);\nawait writeFile(\"download.pdf\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.Sessions.Signatures.DownloadEvidence(ctx, \"11111111-2222-3333-4444-555555555555\", \"feature_signature\", didit.SessionsSignaturesDownloadEvidenceParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.sessions().signatures().downloadEvidence(\"11111111-2222-3333-4444-555555555555\", \"feature_signature\")\n        .writeTo(Path.of(\"download.pdf\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->sessions->signatures->downloadEvidence('11111111-2222-3333-4444-555555555555', 'feature_signature');\n$content->saveTo('download.pdf');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.sessions.signatures.download_evidence(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_signature\"\n)\nFile.binwrite(\"download.pdf\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.Sessions.Signatures.DownloadEvidenceAsync(\"11111111-2222-3333-4444-555555555555\", \"feature_signature\");\nawait content.SaveToAsync(\"download.pdf\");"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/signatures/{nodeId}/fields/{fieldId}/image/": {
      "get": {
        "summary": "Télécharger une image de signature",
        "description": "Télécharger la signature ou les initiales apposées par un signataire sur un champ, au format PNG. Utilisez l'`image_url` du champ dans `signatures[].documents[].fields[]`. Nécessite `read:sessions` ; votre clé API fonctionne.",
        "operationId": "get_v3_session_signature_field_image",
        "x-didit-sdk": {
          "resource": "sessions.signatures",
          "method": "download_field_image",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "La session de vérification des utilisateurs (KYC) ou de vérification d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "description": "L'étape de signature électronique : `node_id` de l'élément dans `signatures[]`.",
            "schema": {
              "type": "string",
              "example": "feature_signature"
            }
          },
          {
            "name": "fieldId",
            "in": "path",
            "required": true,
            "description": "Le champ sur l'exemplaire destiné à ce signataire, comme dans l'`image_url` du champ.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "L'image.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "L'image enregistrée ne correspond plus à son empreinte SHA-256 enregistrée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "code": "signature_document_changed",
                  "detail": "signature_document_changed"
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, ou identifiant ne pouvant pas lire cette session. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "You do not have permission to perform this action."
                }
              }
            }
          },
          "404": {
            "description": "Aucune image ne correspond : la session, l'étape ou le champ n'existe pas, a été supprimé(e) ou ne comporte aucune signature ni initiales appliquées.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Unknown field": {
                    "summary": "Aucun champ de ce type",
                    "value": {
                      "code": "signature_field_not_found",
                      "detail": "signature_field_not_found"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.sessions.signatures.download_field_image(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"feature_signature\",\n    \"11111111-2222-3333-4444-555555555555\",\n)\nwith open(\"download.png\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.sessions.signatures.downloadFieldImage(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_signature\",\n  \"11111111-2222-3333-4444-555555555555\",\n);\nawait writeFile(\"download.png\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.Sessions.Signatures.DownloadFieldImage(ctx, \"11111111-2222-3333-4444-555555555555\", \"feature_signature\", \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.png\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.sessions().signatures().downloadFieldImage(\"11111111-2222-3333-4444-555555555555\", \"feature_signature\", \"11111111-2222-3333-4444-555555555555\")\n        .writeTo(Path.of(\"download.png\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->sessions->signatures->downloadFieldImage('11111111-2222-3333-4444-555555555555', 'feature_signature', '11111111-2222-3333-4444-555555555555');\n$content->saveTo('download.png');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.sessions.signatures.download_field_image(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_signature\",\n  \"11111111-2222-3333-4444-555555555555\"\n)\nFile.binwrite(\"download.png\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.Sessions.Signatures.DownloadFieldImageAsync(\"11111111-2222-3333-4444-555555555555\", \"feature_signature\", \"11111111-2222-3333-4444-555555555555\");\nawait content.SaveToAsync(\"download.png\");"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/signatures/{nodeId}/validate/": {
      "post": {
        "summary": "Valider à nouveau les signatures",
        "description": "Vérifier à nouveau les documents signés d'une étape de Signature électronique. Didit relit chaque PDF signé, vérifie son SHA-256 et, pour une signature avancée (AES), valide la signature PAdES, le certificat, les données de révocation et l'horodatage (une signature simple ne possède pas de signature numérique, seule l'intégrité du fichier est donc vérifiée), puis enregistre le résultat dans le champ `validation` de chaque signataire et renvoie les éléments mis à jour. Aucun document n'est signé à nouveau. Envoyez `signature_id` pour vérifier un seul signataire ; sans cela, chaque signataire de l'étape est vérifié, et l'appel échoue si l'un d'entre eux n'a pas signé.\n\nNécessite `write:sessions` ; votre clé API fonctionne. Dans la console, il s'agit du bouton **Valider à nouveau**.",
        "operationId": "post_v3_session_signature_validate",
        "x-didit-sdk": {
          "resource": "sessions.signatures",
          "method": "validate",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "La session de vérification des utilisateurs (KYC) ou de vérification d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "nodeId",
            "in": "path",
            "required": true,
            "description": "L'étape de signature électronique : `node_id` de l'élément dans `signatures[]`.",
            "schema": {
              "type": "string",
              "example": "feature_signature"
            }
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "signature_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "`id` de l'élément d'un signataire dans `signatures[]`."
                  }
                }
              },
              "example": {
                "signature_id": "0e6c2a8e-6c2f-4b8e-9a51-3f2f6a7d9b10"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Les signataires vérifiés, avec leur `validation` mise à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "signatures": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SignatureResult"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Un PDF signé stocké ne correspond plus au SHA-256 enregistré lors de sa signature.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Document changed": {
                    "summary": "Un fichier signé ne correspond plus à son hachage",
                    "value": {
                      "code": "signature_document_changed",
                      "detail": "signature_document_changed"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, ou identifiant ne pouvant pas lire cette session. Une clé manquante renvoie `403` ; une clé erronée, révoquée ou expirée renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "You do not have permission to perform this action."
                }
              }
            }
          },
          "404": {
            "description": "Aucune signature ne correspond : la session, l'étape ou le signataire n'existe pas ou a été supprimé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Unknown signer": {
                    "summary": "Aucune signature de ce type dans cette étape",
                    "value": {
                      "code": "signature_not_found",
                      "detail": "signature_not_found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Un signataire de l'étape n'a pas signé, il n'y a donc rien à valider.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not signed": {
                    "summary": "Un signataire n'a pas encore signé",
                    "value": {
                      "code": "signature_not_signed",
                      "detail": "signature_not_signed"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.signatures.validate(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"feature_signature\",\n    signature_id=\"0e6c2a8e-6c2f-4b8e-9a51-3f2f6a7d9b10\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.signatures.validate(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_signature\",\n  {\n    signature_id: \"0e6c2a8e-6c2f-4b8e-9a51-3f2f6a7d9b10\",\n  },\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Signatures.Validate(ctx, \"11111111-2222-3333-4444-555555555555\", \"feature_signature\", didit.SessionsSignaturesValidateParams{\n\tSignatureID: didit.String(\"0e6c2a8e-6c2f-4b8e-9a51-3f2f6a7d9b10\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsSignaturesValidateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().signatures().validate(\"11111111-2222-3333-4444-555555555555\", \"feature_signature\", SessionsSignaturesValidateParams.builder()\n        .signatureId(\"0e6c2a8e-6c2f-4b8e-9a51-3f2f6a7d9b10\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->signatures->validate('11111111-2222-3333-4444-555555555555', 'feature_signature', [\n    'signature_id' => '0e6c2a8e-6c2f-4b8e-9a51-3f2f6a7d9b10',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.signatures.validate(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"feature_signature\",\n  signature_id: \"0e6c2a8e-6c2f-4b8e-9a51-3f2f6a7d9b10\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Signatures.ValidateAsync(\"11111111-2222-3333-4444-555555555555\", \"feature_signature\", new SessionsSignaturesValidateParams\n{\n    SignatureId = \"0e6c2a8e-6c2f-4b8e-9a51-3f2f6a7d9b10\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/document-ai/{sessionId}/documents/{documentUuid}/": {
      "patch": {
        "summary": "Mettre à jour un document Document AI",
        "description": "Corriger les champs extraits par Document AI à partir d'un document téléversé, définir son statut d'examen, ou les deux, sur une session KYC ou KYB. `extracted_data` doit être un objet JSON et est fusionné clé par clé : une clé envoyée remplace la valeur stockée (une clé envoyée avec `null` est stockée sous la forme `null`) et les clés omises conservent leur valeur. Le statut du document alimente le résultat Document AI de son nœud de workflow dans la décision de la session ; le statut de la session lui-même n'est pas recalculé. Chaque appel réussi, y compris s'il ne modifie rien, envoie un [webhook](https://docs.didit.me/fr/integration/webhooks) `data.updated` avec le déclencheur `manual_review`. Une clé API restreinte nécessite `decisions: write` ; voir [Document AI](https://docs.didit.me/fr/core-technology/document-ai/overview).",
        "operationId": "patch_v3_document_ai_document",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_document_ai_data",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification (le `session_id` renvoyé par `POST /v3/session/`). Accepte les identifiants de session de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) : le serveur résout l'identifiant pour les deux types de session. Doit être un UUID bien formé ; une valeur malformée ne correspond pas à la route et renvoie une erreur HTML `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "documentUuid",
            "in": "path",
            "required": true,
            "description": "UUID du document Document AI (`document_ai_documents[].items[].uuid` dans `GET /v3/session/{sessionId}/decision/`). Il doit appartenir à la session présente dans le chemin.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "44444444-5555-6666-7777-888888888888"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "extracted_data": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Clés de champ (les clés que vous avez configurées pour le document) et leurs valeurs corrigées. Doit être un objet JSON ; fusionné clé par clé dans les données stockées. Omettez-le plutôt que d'envoyer `null`, qui renvoie un code `400`.",
                    "example": {
                      "invoice_number": "INV-2026-0042"
                    }
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "Approved",
                      "Declined",
                      "In Review",
                      "Not Finished"
                    ],
                    "description": "Nouveau statut d'examen du document.",
                    "example": "Approved"
                  }
                }
              },
              "example": {
                "extracted_data": {
                  "invoice_number": "INV-2026-0042"
                },
                "status": "Approved"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/document-ai/11111111-2222-3333-4444-555555555555/documents/44444444-5555-6666-7777-888888888888/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"extracted_data\": {\"invoice_number\": \"INV-2026-0042\"}, \"status\": \"Approved\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_document_ai_data(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"44444444-5555-6666-7777-888888888888\",\n    extracted_data={\"invoice_number\": \"INV-2026-0042\"},\n    status=\"Approved\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateDocumentAiData(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"44444444-5555-6666-7777-888888888888\",\n  {\n    extracted_data: { invoice_number: \"INV-2026-0042\" },\n    status: \"Approved\",\n  },\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateDocumentAiData(ctx, \"11111111-2222-3333-4444-555555555555\", \"44444444-5555-6666-7777-888888888888\", didit.SessionsUpdateDocumentAiDataParams{\n\tExtractedData: didit.Some(map[string]any{\"invoice_number\": \"INV-2026-0042\"}),\n\tStatus:        didit.Some(didit.SessionsUpdateDocumentAiDataParamsStatus(\"Approved\")),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.SessionsUpdateDocumentAiDataParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateDocumentAiData(\"11111111-2222-3333-4444-555555555555\", \"44444444-5555-6666-7777-888888888888\", SessionsUpdateDocumentAiDataParams.builder()\n        .extractedData(Map.of(\"invoice_number\", \"INV-2026-0042\"))\n        .status(SessionsUpdateDocumentAiDataParams.Status.of(\"Approved\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateDocumentAiData('11111111-2222-3333-4444-555555555555', '44444444-5555-6666-7777-888888888888', [\n    'extracted_data' => ['invoice_number' => 'INV-2026-0042'],\n    'status' => 'Approved',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_document_ai_data(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"44444444-5555-6666-7777-888888888888\",\n  extracted_data: { invoice_number: \"INV-2026-0042\" },\n  status: \"Approved\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateDocumentAiDataAsync(\"11111111-2222-3333-4444-555555555555\", \"44444444-5555-6666-7777-888888888888\", new SessionsUpdateDocumentAiDataParams\n{\n    ExtractedData = new Dictionary<string, object> { [\"invoice_number\"] = \"INV-2026-0042\" },\n    Status = new SessionsUpdateDocumentAiDataParamsStatus(\"Approved\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Document mis à jour. Renvoie le document après la fusion.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "uuid",
                    "document_key",
                    "original_filename",
                    "file_url",
                    "status",
                    "extracted_data"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant du document."
                    },
                    "document_key": {
                      "type": "string",
                      "description": "Le document configuré auquel correspond ce téléversement."
                    },
                    "original_filename": {
                      "type": "string",
                      "nullable": true,
                      "description": "Nom de fichier avec lequel le document a été téléversé."
                    },
                    "file_url": {
                      "type": "string",
                      "nullable": true,
                      "description": "Chemin de stockage du fichier téléversé. Il ne s'agit pas d'un lien de téléchargement : lisez l'URL pré-signée `file_url` depuis la décision de session pour télécharger le fichier."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "Not Finished",
                        "Approved",
                        "Declined",
                        "In Review",
                        "Resub Requested"
                      ],
                      "description": "Statut d'examen du document."
                    },
                    "extracted_data": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Tous les champs extraits après la fusion, indexés par clé de champ."
                    }
                  }
                },
                "example": {
                  "uuid": "44444444-5555-6666-7777-888888888888",
                  "document_key": "invoice",
                  "original_filename": "invoice-2026-09.pdf",
                  "file_url": "document_ai/11111111-2222-3333-4444-555555555555-66666666-7777-8888-9999-000000000000.pdf",
                  "status": "Approved",
                  "extracted_data": {
                    "invoice_number": "INV-2026-0042",
                    "total_amount": 1250.0,
                    "issue_date": "2026-09-01"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation, vérifiée avant la recherche du document : `status` ne fait pas partie des valeurs autorisées, ou `extracted_data` envoyé avec la valeur `null`.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid status": {
                    "summary": "status n'est pas dans l'enum",
                    "value": {
                      "status": [
                        "\"Rejected\" is not a valid choice."
                      ]
                    }
                  },
                  "Null extracted_data": {
                    "summary": "extracted_data est null",
                    "value": {
                      "extracted_data": [
                        "This field may not be null."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée ou se trouve en dehors des limites d'une clé restreinte, ou aucun document actuel avec cet UUID ne lui appartient. La recherche de session s'exécute avant la vérification des identifiants, donc un `sessionId` inconnu renvoie `404` même sans clé valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID n'existe, ou elle a été supprimée",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside key limits": {
                    "summary": "La session se trouve en dehors des limites d'une clé restreinte (également renvoyée pour une session supprimée il y a quelques instants)",
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "Unknown document": {
                    "summary": "documentUuid n'appartient pas à la session",
                    "value": {
                      "detail": "Document AI document not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 300 requêtes d'écriture (POST, PATCH, DELETE) par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/aml/dataset-freshness/": {
      "get": {
        "summary": "Obtenir la fraîcheur du jeu de données AML",
        "description": "Indique la fraîcheur des jeux de données utilisés pour le filtrage AML, par famille de sources (`sanctions`, `pep`, `warnings`, `adverse_media`), comme élément d'audit pour la [surveillance AML continue](https://docs.didit.me/fr/core-technology/aml-screening/continuous-monitoring-aml-screening#prouver-que-la-surveillance-a-bien-été-exécutée). La réponse s'applique à l'ensemble de la plateforme : aucune session dans le chemin d'accès, aucune donnée client dans le corps, la même réponse pour chaque application.\n\nRenvoie systématiquement `200` pour une clé acceptée. Vérifiez `availability` en premier : lorsqu'elle ne vaut pas `available`, `dataset_freshness` est `null`. Les dates ne sont jamais estimées : une famille dont les jeux de données n'ont indiqué aucune date est absente de `sources`, et une famille où seuls certains jeux de données en ont indiqué une a `oldest_updated_at: null`. Les relevés sont effectués pendant l'exécution de la surveillance continue, pas à chaque appel ; `captured_at` indique la date du relevé.\n\nUne clé API restreinte nécessite `sessions: read` ; une clé limitée à certains workflows ou aux sessions approuvées ne peut pas appeler cet endpoint. Rien n'est facturé.",
        "operationId": "get_aml_dataset_freshness",
        "x-didit-sdk": {
          "resource": "aml",
          "method": "retrieve_dataset_freshness",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "parameters": [],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/aml/dataset-freshness/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.aml.retrieve_dataset_freshness()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.aml.retrieveDatasetFreshness();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.AML.RetrieveDatasetFreshness(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.aml().retrieveDatasetFreshness();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->aml->retrieveDatasetFreshness();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.aml.retrieve_dataset_freshness\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Aml.RetrieveDatasetFreshnessAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le relevé le plus récent de fraîcheur du jeu de données, ou `null` avec la raison.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dataset_freshness",
                    "availability"
                  ],
                  "properties": {
                    "dataset_freshness": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/AMLDatasetFreshness"
                        }
                      ],
                      "nullable": true,
                      "description": "Le dernier relevé, ou `null` lorsque `availability` n'est pas `available`."
                    },
                    "availability": {
                      "type": "string",
                      "enum": [
                        "available",
                        "not_configured",
                        "not_yet_collected"
                      ],
                      "description": "`available` lorsqu'un relevé existe ; `not_configured` lorsque les dates du jeu de données ne sont pas collectées dans cet environnement ; `not_yet_collected` lorsque la collecte est configurée mais qu'aucun relevé n'existe encore."
                    }
                  }
                },
                "examples": {
                  "Available": {
                    "value": {
                      "dataset_freshness": {
                        "captured_at": "2026-10-17T06:00:12.345678+00:00",
                        "provider": "aml_data_source",
                        "catalog_version": "20261017054500-abc",
                        "sources": {
                          "sanctions": {
                            "last_updated_at": "2026-10-17T04:10:00+00:00",
                            "oldest_updated_at": "2026-10-15T22:30:00+00:00",
                            "dataset_count": 48,
                            "dated_dataset_count": 48
                          },
                          "pep": {
                            "last_updated_at": "2026-10-16T23:05:00+00:00",
                            "oldest_updated_at": null,
                            "dataset_count": 12,
                            "dated_dataset_count": 11
                          }
                        }
                      },
                      "availability": "available"
                    }
                  },
                  "Not collected yet": {
                    "value": {
                      "dataset_freshness": null,
                      "availability": "not_yet_collected"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré. Seule une clé créée avec une date d'expiration peut expirer ; après cette date, chaque requête effectuée avec celle-ci renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Une clé manquante reçoit le message générique ; une clé erronée, révoquée ou expirée reçoit `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without sessions read": {
                    "value": {
                      "detail": "This API key has no read access to sessions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the key's IP list": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 600 requêtes GET par minute avec cette clé API. Attendez le nombre de secondes indiqué dans `Retry-After`, puis réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes avant la réinitialisation de la fenêtre actuelle d'une minute.",
                "schema": {
                  "type": "integer",
                  "example": 23
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées par minute dans ce budget.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix auquel la fenêtre se réinitialise.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/lists/": {
      "get": {
        "summary": "Lister les listes",
        "description": "Renvoie les listes de l'application, les plus récentes en premier : les listes système fournies par Didit (une liste de blocage par type d'entrée, la liste personnalisée **High Risk Countries** et toute liste d'autorisation système) ainsi que les listes d'autorisation et listes personnalisées que vous avez créées. Filtrez avec `list_type` et `entry_type` ; les listes supprimées n'apparaissent jamais. Les résultats sont paginés avec `limit` et `offset`. Une clé API restreinte nécessite `workflows: read`. Consultez [Listes](https://docs.didit.me/fr/management-api/lists/overview) pour connaître le rôle de chaque type de liste.",
        "operationId": "list_lists",
        "x-didit-sdk": {
          "resource": "lists",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "parameters": [
          {
            "name": "list_type",
            "in": "query",
            "required": false,
            "description": "Uniquement les listes de ce type.",
            "schema": {
              "type": "string",
              "enum": [
                "blocklist",
                "allowlist",
                "custom"
              ]
            }
          },
          {
            "name": "entry_type",
            "in": "query",
            "required": false,
            "description": "Uniquement les listes de ce type d'entrée.",
            "schema": {
              "type": "string",
              "enum": [
                "face",
                "document",
                "phone",
                "email",
                "ip_address",
                "device_fingerprint",
                "wallet_address",
                "bank_account",
                "country",
                "user",
                "business",
                "key"
              ]
            }
          },
          {
            "name": "ordering",
            "in": "query",
            "required": false,
            "description": "Ordre de tri : `-created_at` (le plus récent en premier, par défaut) ou `created_at` (le plus ancien en premier).",
            "schema": {
              "type": "string",
              "enum": [
                "-created_at",
                "created_at"
              ],
              "default": "-created_at"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Taille de page. Vaut 50 par défaut. Une valeur supérieure à 1000000 renvoie `400` ; une valeur égale à zéro, négative ou non numérique repasse par défaut à 50.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Indice de départ (base zéro) du premier élément à retourner. Privilégiez l'utilisation de `next`. Une valeur supérieure à 1000000 retourne `400` ; une valeur négative ou non numérique revient par défaut à 0.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/lists/?list_type=blocklist' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.lists.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.lists.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Lists.ListAutoPaging(ctx, didit.ListsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.lists().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->lists->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.lists.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Lists.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de listes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Nombre total de listes correspondant aux filtres."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ComplianceList"
                      }
                    }
                  }
                },
                "examples": {
                  "Lists": {
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "22222222-3333-4444-5555-666666666666",
                          "name": "Trusted office IPs",
                          "description": "Office egress ranges",
                          "list_type": "allowlist",
                          "entry_type": "ip_address",
                          "is_system": false,
                          "entry_count": 3,
                          "last_entry_added_at": "2026-10-02T08:15:27.501334Z",
                          "created_at": "2026-09-30T13:20:45.889120Z",
                          "updated_at": "2026-09-30T13:20:45.889120Z"
                        },
                        {
                          "uuid": "11111111-2222-3333-4444-555555555555",
                          "name": "Face Blocklist",
                          "description": "Blocked biometric faces. When a face matching an entry in this list is detected during liveness verification, the session will be automatically declined.",
                          "list_type": "blocklist",
                          "entry_type": "face",
                          "is_system": true,
                          "entry_count": 12,
                          "last_entry_added_at": "2026-10-09T16:42:03.118204Z",
                          "created_at": "2026-01-14T10:02:11.402917Z",
                          "updated_at": "2026-01-14T10:02:11.402917Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Un paramètre de requête est invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown list type": {
                    "value": {
                      "list_type": [
                        "\"denylist\" is not a valid choice."
                      ]
                    }
                  },
                  "Unsupported ordering": {
                    "value": {
                      "ordering": [
                        "\"name\" is not a valid choice."
                      ]
                    }
                  },
                  "Limit too large": {
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: read` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no read access to workflows."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "La limite de lecture partagée de 600 requêtes par minute et par clé API a été dépassée. Respectez l'en-tête `Retry-After` avant de réessayer.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer une liste",
        "description": "Crée une liste d'autorisation ou une liste personnalisée dans l'application à laquelle appartient la clé API. Les listes de blocage ne peuvent pas être créées : Didit provisionne une liste de blocage système par type d'entrée, et vous pouvez y ajouter des éléments avec [Créer une entrée de liste](https://docs.didit.me/fr/management-api/lists/create-entry). `entry_type` ne peut pas être modifié après la création et détermine la manière dont les valeurs d'entrée sont validées et mises en correspondance. Les entrées de liste d'autorisation marquent les éléments correspondants comme fiables (par exemple, une liste d'autorisation faciale ignore l'action de visage dupliqué) et ne prévalent jamais sur une correspondance de liste de blocage ; référencez n'importe quelle liste depuis une condition de règle de workflow ou de transaction avec `value_type: \"list\"`. Une clé API restreinte nécessite `workflows: write`.",
        "operationId": "create_list",
        "x-didit-sdk": {
          "resource": "lists",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "list_type",
                  "entry_type"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "Nom de la liste. Doit être différent du nom de toutes les autres listes de l'application, listes système incluses."
                  },
                  "description": {
                    "type": "string",
                    "default": "",
                    "description": "Description en texte libre optionnelle."
                  },
                  "list_type": {
                    "type": "string",
                    "enum": [
                      "allowlist",
                      "custom"
                    ],
                    "description": "`allowlist` ou `custom`. `blocklist` est refusé avec `400`."
                  },
                  "entry_type": {
                    "type": "string",
                    "enum": [
                      "face",
                      "document",
                      "phone",
                      "email",
                      "ip_address",
                      "device_fingerprint",
                      "wallet_address",
                      "bank_account",
                      "country",
                      "user",
                      "business",
                      "key"
                    ],
                    "description": "Ce que contient la liste : `face`, `document` (numéro de document), `phone`, `email`, `ip_address` (adresse ou plage CIDR), `device_fingerprint`, `wallet_address`, `bank_account`, `country` (ISO 3166-1 alpha-3), `user` ou `business` (vos `vendor_data`), ou `key` (toute chaîne). Cela détermine la manière dont les valeurs des entrées sont validées et mises en correspondance. Ne peut pas être modifié ultérieurement."
                  }
                }
              },
              "examples": {
                "IP allowlist": {
                  "value": {
                    "name": "Trusted office IPs",
                    "description": "Office egress ranges",
                    "list_type": "allowlist",
                    "entry_type": "ip_address"
                  }
                },
                "Custom country list": {
                  "value": {
                    "name": "Enhanced due diligence countries",
                    "list_type": "custom",
                    "entry_type": "country"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/lists/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"name\": \"Trusted office IPs\",\n    \"description\": \"Office egress ranges\",\n    \"list_type\": \"allowlist\",\n    \"entry_type\": \"ip_address\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.lists.create(\n    name=\"Trusted office IPs\",\n    description=\"Office egress ranges\",\n    list_type=\"allowlist\",\n    entry_type=\"ip_address\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.lists.create({\n  name: \"Trusted office IPs\",\n  description: \"Office egress ranges\",\n  list_type: \"allowlist\",\n  entry_type: \"ip_address\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Lists.Create(ctx, didit.ListsCreateParams{\n\tName:        \"Trusted office IPs\",\n\tDescription: didit.String(\"Office egress ranges\"),\n\tListType:    \"allowlist\",\n\tEntryType:   \"ip_address\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.ListsCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.lists().create(ListsCreateParams.builder()\n        .name(\"Trusted office IPs\")\n        .description(\"Office egress ranges\")\n        .listType(ListsCreateParams.ListType.of(\"allowlist\"))\n        .entryType(ListsCreateParams.EntryType.of(\"ip_address\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->lists->create([\n    'name' => 'Trusted office IPs',\n    'description' => 'Office egress ranges',\n    'list_type' => 'allowlist',\n    'entry_type' => 'ip_address',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.lists.create(\n  name: \"Trusted office IPs\",\n  description: \"Office egress ranges\",\n  list_type: \"allowlist\",\n  entry_type: \"ip_address\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Lists.CreateAsync(new ListsCreateParams\n{\n    Name = \"Trusted office IPs\",\n    Description = \"Office egress ranges\",\n    ListType = \"allowlist\",\n    EntryType = \"ip_address\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "La liste a été créée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComplianceList"
                },
                "examples": {
                  "New allowlist": {
                    "value": {
                      "uuid": "22222222-3333-4444-5555-666666666666",
                      "name": "Trusted office IPs",
                      "description": "Office egress ranges",
                      "list_type": "allowlist",
                      "entry_type": "ip_address",
                      "is_system": false,
                      "entry_count": 0,
                      "last_entry_added_at": null,
                      "created_at": "2026-10-12T09:15:44.031876Z",
                      "updated_at": "2026-10-12T09:15:44.031876Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le corps est invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Blocklist refused": {
                    "value": {
                      "list_type": [
                        "Cannot create additional blocklist lists. System blocklists are auto-created for each application."
                      ]
                    }
                  },
                  "Duplicate name": {
                    "value": {
                      "name": [
                        "A list with this name already exists for this application."
                      ]
                    }
                  },
                  "Missing fields": {
                    "value": {
                      "name": [
                        "This field is required."
                      ],
                      "list_type": [
                        "This field is required."
                      ],
                      "entry_type": [
                        "This field is required."
                      ]
                    }
                  },
                  "Unknown entry type": {
                    "value": {
                      "entry_type": [
                        "\"iban\" is not a valid choice."
                      ]
                    }
                  },
                  "Name too long": {
                    "value": {
                      "name": [
                        "Ensure this field has no more than 255 characters."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: write` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no write access to workflows."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/lists/{list_uuid}/": {
      "get": {
        "summary": "Obtenir une liste",
        "description": "Renvoie une liste de l'application avec son nombre d'entrées et la date à laquelle sa dernière entrée a été ajoutée. Une liste appartenant à une autre application, ou ayant été supprimée, renvoie `404`. Cela renvoie uniquement la liste : lisez ses valeurs avec [Lister les entrées de la liste](https://docs.didit.me/fr/management-api/lists/list-entries). Une clé API restreinte nécessite `workflows: read`.",
        "operationId": "get_list",
        "x-didit-sdk": {
          "resource": "lists",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "parameters": [
          {
            "name": "list_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la liste, tel que renvoyé par Lister les listes ou Créer une liste.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/lists/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.lists.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.lists.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Lists.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.lists().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->lists->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.lists.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Lists.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La liste.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComplianceList"
                },
                "examples": {
                  "System face blocklist": {
                    "value": {
                      "uuid": "11111111-2222-3333-4444-555555555555",
                      "name": "Face Blocklist",
                      "description": "Blocked biometric faces. When a face matching an entry in this list is detected during liveness verification, the session will be automatically declined.",
                      "list_type": "blocklist",
                      "entry_type": "face",
                      "is_system": true,
                      "entry_count": 12,
                      "last_entry_added_at": "2026-10-09T16:42:03.118204Z",
                      "created_at": "2026-01-14T10:02:11.402917Z",
                      "updated_at": "2026-01-14T10:02:11.402917Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: read` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no read access to workflows."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune liste avec cet UUID n'existe dans l'application de la clé API, ou elle a été supprimée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No List matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "La limite de lecture partagée de 600 requêtes par minute et par clé API a été dépassée. Respectez l'en-tête `Retry-After` avant de réessayer.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour une liste",
        "description": "Renomme une liste ou modifie sa description. Seuls `name` et `description` sont pris en compte ; tout autre champ est ignoré, de sorte que `list_type` et `entry_type` conservent les valeurs avec lesquelles ils ont été créés. Les listes système ne peuvent pas être modifiées et renvoient `400`. La réponse contient uniquement `name` et `description` : appelez [Get a list](https://docs.didit.me/fr/management-api/lists/get) pour obtenir la liste complète. Une clé API restreinte nécessite `workflows: write`.",
        "operationId": "update_list",
        "x-didit-sdk": {
          "resource": "lists",
          "method": "update",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "parameters": [
          {
            "name": "list_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la liste, tel que renvoyé par Lister les listes ou Créer une liste.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "Nouveau nom. Doit différer du nom de toutes les autres listes de l'application."
                  },
                  "description": {
                    "type": "string",
                    "description": "Nouvelle description. Envoyez une chaîne vide pour l'effacer."
                  }
                }
              },
              "examples": {
                "Rename": {
                  "value": {
                    "name": "Trusted office and VPN IPs"
                  }
                },
                "Rename and describe": {
                  "value": {
                    "name": "Trusted office and VPN IPs",
                    "description": "Office egress ranges and the corporate VPN"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/lists/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"name\": \"Trusted office and VPN IPs\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.lists.update(\n    \"11111111-2222-3333-4444-555555555555\",\n    name=\"Trusted office and VPN IPs\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.lists.update(\"11111111-2222-3333-4444-555555555555\", {\n  name: \"Trusted office and VPN IPs\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Lists.Update(ctx, \"11111111-2222-3333-4444-555555555555\", didit.ListsUpdateParams{\n\tName: didit.String(\"Trusted office and VPN IPs\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.ListsUpdateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.lists().update(\"11111111-2222-3333-4444-555555555555\", ListsUpdateParams.builder()\n        .name(\"Trusted office and VPN IPs\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->lists->update('11111111-2222-3333-4444-555555555555', [\n    'name' => 'Trusted office and VPN IPs',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.lists.update(\n  \"11111111-2222-3333-4444-555555555555\",\n  name: \"Trusted office and VPN IPs\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Lists.UpdateAsync(\"11111111-2222-3333-4444-555555555555\", new ListsUpdateParams\n{\n    Name = \"Trusted office and VPN IPs\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La liste a été mise à jour. Seuls les champs modifiables sont renvoyés.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "name",
                    "description"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Le nom de la liste après la mise à jour."
                    },
                    "description": {
                      "type": "string",
                      "description": "La description de la liste après la mise à jour."
                    }
                  }
                },
                "examples": {
                  "Renamed": {
                    "value": {
                      "name": "Trusted office and VPN IPs",
                      "description": "Office egress ranges"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "La liste est une liste système, ou le corps de la requête est invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "System list": {
                    "value": {
                      "non_field_errors": [
                        "System lists cannot be modified."
                      ]
                    }
                  },
                  "Duplicate name": {
                    "value": {
                      "name": [
                        "A list with this name already exists for this application."
                      ]
                    }
                  },
                  "Blank name": {
                    "value": {
                      "name": [
                        "This field may not be blank."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: write` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no write access to workflows."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune liste avec cet UUID n'existe dans l'application de la clé API, ou elle a été supprimée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No List matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Supprimer une liste",
        "description": "Supprime une liste d'autorisation ou une liste personnalisée ainsi que ses entrées. La suppression est irréversible : la liste et ses entrées n'apparaissent plus dans aucune lecture, et les conditions de règles de workflow et de transaction qui font référence à la liste l'évaluent dès lors comme une liste vide. Les sessions et transactions déjà évaluées conservent leurs résultats, et le nom peut être réutilisé pour une nouvelle liste. Les listes système ne peuvent pas être supprimées et renvoient `400` ; pour en vider une, [supprimez ses entrées](https://docs.didit.me/fr/management-api/lists/delete-entry). Une clé API restreinte nécessite `workflows: write`.",
        "operationId": "delete_list",
        "x-didit-sdk": {
          "resource": "lists",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "parameters": [
          {
            "name": "list_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la liste, tel que renvoyé par Lister les listes ou Créer une liste.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/lists/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.lists.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.lists.delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.Lists.Delete(ctx, \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.lists().delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->lists->delete('11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.lists.delete(\"11111111-2222-3333-4444-555555555555\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.Lists.DeleteAsync(\"11111111-2222-3333-4444-555555555555\");"
          }
        ],
        "responses": {
          "204": {
            "description": "La liste et ses entrées ont été supprimées. Aucun corps de réponse."
          },
          "400": {
            "description": "La liste est une liste système.",
            "content": {
              "application/json": {
                "examples": {
                  "System list": {
                    "value": {
                      "detail": "System lists cannot be deleted."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: write` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no write access to workflows."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune liste avec cet UUID n'existe dans l'application de la clé API, ou elle a déjà été supprimée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No List matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/lists/{list_uuid}/entries/": {
      "get": {
        "summary": "Lister les entrées de liste",
        "description": "Renvoie les entrées actuelles d'une liste, les plus récentes en premier. `search` fait correspondre une partie de la valeur `value` ou de `display_label` d'une entrée sans tenir compte de la casse, et `reference_session_id` restreint les résultats aux entrées issues d'une session de vérification de personne. Les URL d'images dans `metadata` sont des URL signées à courte durée de vie générées à nouveau à chaque appel ; une clé API restreinte sans `media: read` reçoit `null` à leur place. Une clé API restreinte nécessite `workflows: read`.",
        "operationId": "list_list_entries",
        "x-didit-sdk": {
          "resource": "lists.entries",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "parameters": [
          {
            "name": "list_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la liste, tel que renvoyé par Lister les listes ou Créer une liste.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Texte insensible à la casse que la `value` ou le `display_label` de l'entrée doit contenir.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reference_session_id",
            "in": "query",
            "required": false,
            "description": "Uniquement les entrées issues de cette session de vérification d'une personne, par exemple pour voir lesquels de ses visages sont déjà répertoriés.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Taille de page. Vaut 50 par défaut. Une valeur supérieure à 1000000 renvoie `400` ; une valeur égale à zéro, négative ou non numérique repasse par défaut à 50.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Indice de départ (base zéro) du premier élément à retourner. Privilégiez l'utilisation de `next`. Une valeur supérieure à 1000000 retourne `400` ; une valeur négative ou non numérique revient par défaut à 0.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/lists/11111111-2222-3333-4444-555555555555/entries/?search=example.com' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.lists.entries.list(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.lists.entries.list(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Lists.Entries.ListAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.ListsEntriesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.lists().entries().list(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->lists->entries->list('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.lists.entries.list(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Lists.Entries.ListAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page d'entrées, les plus récentes en premier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Nombre total d'entrées correspondant aux filtres."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ComplianceListEntry"
                      }
                    }
                  }
                },
                "examples": {
                  "Entries": {
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "bbbbbbbb-cccc-dddd-eeee-ffffffffffff",
                          "value": "X1234567",
                          "display_label": "Jane Doe - X1234567",
                          "comment": "",
                          "added_by": "api",
                          "reference_session_id": "33333333-4444-5555-6666-777777777777",
                          "reference_session_number": 1042,
                          "reference_session_type": "kyc",
                          "reference_object_uuid": "66666666-7777-8888-9999-000000000000",
                          "metadata": {
                            "full_name": "Jane Doe",
                            "issuing_state": "ESP",
                            "document_type": "ID",
                            "region": "",
                            "document_number": "X1234567"
                          },
                          "created_at": "2026-10-12T10:06:12.774915Z"
                        },
                        {
                          "uuid": "eeeeeeee-ffff-0000-1111-222222222222",
                          "value": "y7654321",
                          "display_label": "",
                          "comment": "Reported by a partner",
                          "added_by": "api",
                          "reference_session_id": null,
                          "reference_session_number": null,
                          "reference_session_type": null,
                          "reference_object_uuid": null,
                          "metadata": null,
                          "created_at": "2026-10-03T07:48:30.552810Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Un paramètre de requête est invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid session id": {
                    "value": {
                      "reference_session_id": [
                        "Must be a valid UUID."
                      ]
                    }
                  },
                  "Limit too large": {
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: read` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no read access to workflows."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune liste avec cet UUID n'existe dans l'application de la clé API, ou elle a été supprimée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "List not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "La limite de lecture partagée de 600 requêtes par minute et par clé API a été dépassée. Respectez l'en-tête `Retry-After` avant de réessayer.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer une entrée de liste",
        "description": "Ajoute une entrée à une liste, selon l'une des trois méthodes suivantes : par `value` ; à partir d'une session de vérification avec `reference_session_id`, où Didit lit la valeur depuis l'enregistrement le plus récent de la session correspondant au type d'entrée de la liste et lui associe l'entrée ; ou par `value` avec un `reference_object_uuid` et un `metadata.reference_type` pointant vers une transaction, un utilisateur ou une entreprise. Sur les listes de blocage système de visages, documents, téléphones et e-mails, l'enregistrement lu depuis la session est également marqué comme placé sur liste de blocage, de sorte que les nouvelles sessions correspondantes sont refusées ; sur les listes de blocage système d'utilisateurs et d'entreprises, les utilisateurs ou entreprises correspondants passent à l'état `BLOCKED`. Les sessions et transactions déjà terminées ne sont pas modifiées. Une clé API restreinte nécessite `workflows: write`. Consultez [Créer une entrée de liste](https://docs.didit.me/fr/management-api/lists/create-entry) pour chaque mode.",
        "operationId": "create_list_entry",
        "x-didit-sdk": {
          "resource": "lists.entries",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "parameters": [
          {
            "name": "list_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la liste à laquelle ajouter l'élément. Pour un visage dont vous ne disposez que sous forme d'image, utilisez plutôt Téléverser un visage dans une liste.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Envoyez `value`, `reference_session_id`, ou les deux. Les champs applicables dépendent du `entry_type` de la liste.",
                "properties": {
                  "value": {
                    "type": "string",
                    "description": "La valeur à inscrire sur la liste, validée selon l'`entry_type` de la liste : `email` une adresse e-mail valide ; `phone` un numéro international valide, stocké au format E.164 ; `ip_address` une adresse IP ou une plage CIDR (par exemple `10.0.0.0/8`) ; `device_fingerprint` au moins 8 caractères parmi lettres, chiffres, `-`, `_`, `:` et `.` (une liste de blocage refuse une empreinte signalée par plusieurs appareils distincts) ; `country` un code ISO 3166-1 alpha-2 ou alpha-3, stocké en alpha-3 ; `user` et `business` le `vendor_data` ; tout autre type une chaîne non vide. Stocké en minuscules sauf pour les numéros de téléphone et les codes pays, et une liste conserve chaque valeur une seule fois (insensible à la casse). Requis sauf si `reference_session_id` est envoyé ; doit être laissé vide avec un `face_image_source` de capture de document."
                  },
                  "reference_session_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Une session de vérification d'utilisateur ou d'entreprise de votre application depuis laquelle extraire la valeur. Didit lit l'enregistrement le plus récent de la session correspondant au type d'entrée de la liste (`face`, `document`, `phone`, `email`, `ip_address` ou `device_fingerprint`), associe l'entrée à la session ainsi qu'à cet enregistrement, et remplit `display_label` et `metadata` pour les documents. Pour une liste de blocage `device_fingerprint`, une session qui ne comporte qu'une empreinte de classe d'appareil, ou qui a été complétée sur plusieurs appareils, est refusée : envoyez l'empreinte exacte dans `value`. Pour les autres types d'entrées, ou lorsque la session ne contient pas un tel enregistrement, envoyez également `value` ; votre `value` est alors stockée et l'entrée reste associée à la session."
                  },
                  "reference_object_uuid": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID de l'enregistrement représenté par l'entrée lorsqu'elle ne provient pas d'une session : un UUID de transaction, ou le `didit_internal_id` d'un utilisateur ou d'une entreprise. Associez-le à `metadata.reference_type`. Remplacé par l'enregistrement de la session lorsque `reference_session_id` en fournit un."
                  },
                  "face_image_source": {
                    "type": "string",
                    "enum": [
                      "liveness",
                      "front_image_camera_front",
                      "back_image_camera_front"
                    ],
                    "default": "liveness",
                    "description": "Listes de visages avec `reference_session_id` : image de la session à partir de laquelle le visage est extrait. `liveness` (par défaut) correspond au selfie de détection du vivant. `front_image_camera_front` et `back_image_camera_front` correspondent aux selfies pris par la caméra frontale pendant que l'utilisateur photographiait le recto ou le verso de son document : acceptés uniquement sur la liste de blocage de visages du système, avec `reference_session_id` et une `value` vide. Chaque selfie ne peut être ajouté qu'une seule fois et doit présenter un seul visage net."
                  },
                  "reference_node_id": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 100,
                    "description": "Avec un `face_image_source` de capture de document : le nœud de vérification d'identité dont le selfie doit être utilisé, pour les workflows qui en comportent plusieurs. Par défaut, il s'agit de la vérification d'identité la plus récente disposant de cette image. Refusé avec `liveness`."
                  },
                  "display_label": {
                    "type": "string",
                    "maxLength": 512,
                    "description": "Libellé lisible par l'humain. Lorsqu'il est vide, Didit en déduit un à partir de la session dans la mesure du possible (par exemple le nom du titulaire et le numéro de document)."
                  },
                  "comment": {
                    "type": "string",
                    "description": "Note en texte libre, telle que le motif d'inscription sur la liste."
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "JSON libre stocké avec l'entrée et renvoyé tel quel. Utilisez `reference_type` et `reference_id` afin que la console crée un lien vers la source. `reference_image_url` et `front_image_url` sont définis par Didit uniquement et sont ignorés si vous les envoyez. Pour une entrée lue depuis une session, les clés de Didit sont fusionnées avec les vôtres.",
                    "properties": {
                      "reference_type": {
                        "type": "string",
                        "enum": [
                          "transaction",
                          "vendor_user",
                          "vendor_business"
                        ],
                        "description": "Ce vers quoi pointe `reference_object_uuid`."
                      },
                      "reference_id": {
                        "type": "string",
                        "description": "Identifiant de l'enregistrement source."
                      }
                    }
                  }
                }
              },
              "examples": {
                "By value": {
                  "value": {
                    "value": "+14155552671",
                    "comment": "Reported fraud"
                  }
                },
                "From a session": {
                  "value": {
                    "reference_session_id": "33333333-4444-5555-6666-777777777777"
                  }
                },
                "Face from a document-capture selfie": {
                  "value": {
                    "reference_session_id": "33333333-4444-5555-6666-777777777777",
                    "face_image_source": "front_image_camera_front"
                  }
                },
                "From a transaction": {
                  "value": {
                    "value": "0x52908400098527886E0F7030069857D2E4169EE7",
                    "reference_object_uuid": "55555555-6666-7777-8888-999999999999",
                    "comment": "Linked to a chargeback",
                    "metadata": {
                      "reference_type": "transaction",
                      "reference_id": "55555555-6666-7777-8888-999999999999"
                    }
                  }
                },
                "Country": {
                  "value": {
                    "value": "PRK",
                    "comment": "Sanctioned jurisdiction"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/lists/11111111-2222-3333-4444-555555555555/entries/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"value\": \"+14155552671\", \"comment\": \"Reported fraud\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.lists.entries.create(\n    \"11111111-2222-3333-4444-555555555555\",\n    value=\"+14155552671\",\n    comment=\"Reported fraud\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.lists.entries.create(\"11111111-2222-3333-4444-555555555555\", {\n  value: \"+14155552671\",\n  comment: \"Reported fraud\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Lists.Entries.Create(ctx, \"11111111-2222-3333-4444-555555555555\", didit.ListsEntriesCreateParams{\n\tValue:   didit.String(\"+14155552671\"),\n\tComment: didit.String(\"Reported fraud\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.ListsEntriesCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.lists().entries().create(\"11111111-2222-3333-4444-555555555555\", ListsEntriesCreateParams.builder()\n        .value(\"+14155552671\")\n        .comment(\"Reported fraud\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->lists->entries->create('11111111-2222-3333-4444-555555555555', [\n    'value' => '+14155552671',\n    'comment' => 'Reported fraud',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.lists.entries.create(\n  \"11111111-2222-3333-4444-555555555555\",\n  value: \"+14155552671\",\n  comment: \"Reported fraud\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Lists.Entries.CreateAsync(\"11111111-2222-3333-4444-555555555555\", new ListsEntriesCreateParams\n{\n    Value = \"+14155552671\",\n    Comment = \"Reported fraud\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "L'entrée a été créée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComplianceListEntry"
                },
                "examples": {
                  "By value": {
                    "value": {
                      "uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                      "value": "+14155552671",
                      "display_label": "",
                      "comment": "Reported fraud",
                      "added_by": "api",
                      "reference_session_id": null,
                      "reference_session_number": null,
                      "reference_session_type": null,
                      "reference_object_uuid": null,
                      "metadata": null,
                      "created_at": "2026-10-12T10:04:51.220391Z"
                    }
                  },
                  "Document from a session": {
                    "value": {
                      "uuid": "bbbbbbbb-cccc-dddd-eeee-ffffffffffff",
                      "value": "X1234567",
                      "display_label": "Jane Doe - X1234567",
                      "comment": "",
                      "added_by": "api",
                      "reference_session_id": "33333333-4444-5555-6666-777777777777",
                      "reference_session_number": 1042,
                      "reference_session_type": "kyc",
                      "reference_object_uuid": "66666666-7777-8888-9999-000000000000",
                      "metadata": {
                        "full_name": "Jane Doe",
                        "issuing_state": "ESP",
                        "document_type": "ID",
                        "region": "",
                        "document_number": "X1234567"
                      },
                      "created_at": "2026-10-12T10:06:12.774915Z"
                    }
                  },
                  "From a transaction": {
                    "value": {
                      "uuid": "dddddddd-eeee-ffff-0000-111111111111",
                      "value": "0x52908400098527886e0f7030069857d2e4169ee7",
                      "display_label": "",
                      "comment": "Linked to a chargeback",
                      "added_by": "api",
                      "reference_session_id": null,
                      "reference_session_number": null,
                      "reference_session_type": null,
                      "reference_object_uuid": "55555555-6666-7777-8888-999999999999",
                      "metadata": {
                        "reference_type": "transaction",
                        "reference_id": "55555555-6666-7777-8888-999999999999"
                      },
                      "created_at": "2026-10-12T10:20:40.117062Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le corps est invalide, la valeur est déjà dans la liste, ou la session ne peut pas fournir la valeur.",
            "content": {
              "application/json": {
                "examples": {
                  "Nothing to list": {
                    "value": {
                      "value": [
                        "Either 'value' or 'reference_session_id' must be provided."
                      ]
                    }
                  },
                  "Duplicate value": {
                    "value": {
                      "value": [
                        "An entry with this value already exists in this list."
                      ]
                    }
                  },
                  "Invalid phone": {
                    "value": {
                      "value": [
                        "Invalid phone number. Provide a valid international number (e.g. +1234567890)."
                      ]
                    }
                  },
                  "Invalid IP": {
                    "value": {
                      "value": [
                        "Invalid IP address or CIDR range (e.g. 192.168.1.1 or 10.0.0.0/24)."
                      ]
                    }
                  },
                  "Invalid country": {
                    "value": {
                      "value": [
                        "Invalid country code: XX. Provide a valid ISO 3166-1 alpha-2 or alpha-3 country code."
                      ]
                    }
                  },
                  "Device-class fingerprint": {
                    "value": {
                      "value": [
                        "This value is a device-class fingerprint: several distinct devices have reported it, so blocklisting it would decline unrelated people. Block the user by document, face, email or phone instead."
                      ]
                    }
                  },
                  "Unknown session": {
                    "value": {
                      "reference_session_id": [
                        "Session not found or does not belong to this application."
                      ]
                    }
                  },
                  "No data in session": {
                    "value": {
                      "value": [
                        "Either provide a 'value' or ensure the session contains data for this entry type."
                      ]
                    }
                  },
                  "Selfie on another list": {
                    "value": {
                      "face_image_source": [
                        "A document-capture selfie can only be added to the face blocklist."
                      ]
                    }
                  },
                  "No clear face in selfie": {
                    "value": {
                      "face_image_source": [
                        "No clear face was found in this selfie, so it cannot be blocklisted."
                      ]
                    }
                  },
                  "Selfie already listed": {
                    "value": {
                      "face_image_source": [
                        "This selfie is already in the blocklist."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: write` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no write access to workflows."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune liste avec cet UUID n'existe dans l'application de la clé API, ou elle a été supprimée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "List not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          },
          "503": {
            "description": "L'analyse faciale du selfie de capture de document est temporairement indisponible. Rien n'a été ajouté ; réessayez plus tard.",
            "content": {
              "application/json": {
                "examples": {
                  "Unavailable": {
                    "value": {
                      "detail": "Service temporarily unavailable. Please try again later."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/lists/{list_uuid}/entries/{entry_uuid}/": {
      "delete": {
        "summary": "Supprimer une entrée de liste",
        "description": "Supprime une entrée d'une liste, listes système incluses. L'entrée cesse immédiatement de correspondre, et la suppression est irréversible : pour répertorier à nouveau la valeur, créez une nouvelle entrée. Sur une liste de blocage système de visages, documents, téléphones ou e-mails, l'enregistrement représenté par l'entrée n'est plus signalé comme figurant sur la liste de blocage ; sur la liste de blocage système des utilisateurs ou des entreprises, les utilisateurs ou les entreprises de l'application dont le champ `vendor_data` est égal à la valeur de l'entrée (ou dont le champ `didit_internal_id` est égal à son `reference_object_uuid`) et qui ont le statut `BLOCKED` repassent à `ACTIVE`. Les sessions et transactions déjà terminées conservent leur statut. Une clé API restreinte nécessite `workflows: write`.",
        "operationId": "delete_list_entry",
        "x-didit-sdk": {
          "resource": "lists.entries",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "parameters": [
          {
            "name": "list_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la liste contenant l'entrée.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "entry_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de l'entrée, tel que renvoyé par Lister les entrées d'une liste ou Créer une entrée de liste.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/lists/11111111-2222-3333-4444-555555555555/entries/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.lists.entries.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.lists.entries.delete(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\n);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.Lists.Entries.Delete(ctx, \"11111111-2222-3333-4444-555555555555\", \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.lists().entries().delete(\"11111111-2222-3333-4444-555555555555\", \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->lists->entries->delete('11111111-2222-3333-4444-555555555555', 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.lists.entries.delete(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\"\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.Lists.Entries.DeleteAsync(\"11111111-2222-3333-4444-555555555555\", \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\");"
          }
        ],
        "responses": {
          "204": {
            "description": "L'entrée a été supprimée. Aucun corps de réponse."
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: write` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no write access to workflows."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune entrée avec cet UUID n'existe dans cette liste, la liste n'appartient pas à l'application de la clé API ou a été supprimée, ou l'entrée a déjà été supprimée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No ListEntry matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/lists/{list_uuid}/entries/face-upload/": {
      "post": {
        "summary": "Téléverser un visage dans une liste",
        "description": "Ajoute un visage à une liste de blocage ou à une liste d'autorisation de visages à partir d'une image JPEG ou PNG encodée en base64, lorsque vous n'avez pas de session de vérification à référencer. Didit détecte les visages dans l'image, utilise le plus grand et crée une entrée dont `value` et `reference_object_uuid` correspondent à l'UUID du nouveau visage. Un visage placé sur liste de blocage entraîne le refus des nouvelles sessions dont le visage correspond ; un visage placé sur liste d'autorisation ignore l'action liée aux visages dupliqués et ne prévaut jamais sur une correspondance avec une liste de blocage. Dans une application sandbox, l'image n'est pas analysée et l'entrée ne correspond à aucun élément. Une clé API avec restriction de portée nécessite `workflows: write`. Pour ajouter un visage à partir d'une session existante, utilisez plutôt [Créer une entrée de liste](https://docs.didit.me/fr/management-api/lists/create-entry) avec `reference_session_id`.",
        "operationId": "upload_list_entry_face",
        "x-didit-sdk": {
          "resource": "lists.entries",
          "method": "upload_face",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Lists"
        ],
        "parameters": [
          {
            "name": "list_uuid",
            "in": "path",
            "required": true,
            "description": "UUID d'une liste avec `entry_type: face` et `list_type: blocklist` ou `allowlist`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "image"
                ],
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "byte",
                    "description": "JPEG ou PNG encodé en Base64, d'au plus 2 Mo une fois décodé, montrant un visage clairement visible. Envoyez la chaîne base64 brute, sans préfixe `data:image/...;base64,`."
                  },
                  "comment": {
                    "type": "string",
                    "default": "",
                    "description": "Note en texte libre optionnelle, telle que le motif de l'inscription sur la liste."
                  }
                }
              },
              "examples": {
                "Face image": {
                  "value": {
                    "image": "/9j/4AAQSkZJRgABAQAAAQABAAD...",
                    "comment": "Known fraud attempt"
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/lists/11111111-2222-3333-4444-555555555555/entries/face-upload/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d \"{\\\"image\\\": \\\"$(base64 < face.jpg | tr -d '\\n')\\\", \\\"comment\\\": \\\"Known fraud attempt\\\"}\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.lists.entries.upload_face(\n    \"11111111-2222-3333-4444-555555555555\",\n    image=\"/9j/4AAQSkZJRgABAQAAAQABAAD...\",\n    comment=\"Known fraud attempt\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.lists.entries.uploadFace(\"11111111-2222-3333-4444-555555555555\", {\n  image: \"/9j/4AAQSkZJRgABAQAAAQABAAD...\",\n  comment: \"Known fraud attempt\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Lists.Entries.UploadFace(ctx, \"11111111-2222-3333-4444-555555555555\", didit.ListsEntriesUploadFaceParams{\n\tImage:   \"/9j/4AAQSkZJRgABAQAAAQABAAD...\",\n\tComment: didit.String(\"Known fraud attempt\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.ListsEntriesUploadFaceParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.lists().entries().uploadFace(\"11111111-2222-3333-4444-555555555555\", ListsEntriesUploadFaceParams.builder()\n        .image(\"/9j/4AAQSkZJRgABAQAAAQABAAD...\")\n        .comment(\"Known fraud attempt\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->lists->entries->uploadFace('11111111-2222-3333-4444-555555555555', [\n    'image' => '/9j/4AAQSkZJRgABAQAAAQABAAD...',\n    'comment' => 'Known fraud attempt',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.lists.entries.upload_face(\n  \"11111111-2222-3333-4444-555555555555\",\n  image: \"/9j/4AAQSkZJRgABAQAAAQABAAD...\",\n  comment: \"Known fraud attempt\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Lists.Entries.UploadFaceAsync(\"11111111-2222-3333-4444-555555555555\", new ListsEntriesUploadFaceParams\n{\n    Image = \"/9j/4AAQSkZJRgABAQAAAQABAAD...\",\n    Comment = \"Known fraud attempt\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "L'entrée faciale a été créée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComplianceListEntry"
                },
                "examples": {
                  "Uploaded face": {
                    "value": {
                      "uuid": "cccccccc-dddd-eeee-ffff-000000000000",
                      "value": "44444444-5555-6666-7777-888888888888",
                      "display_label": "Manually uploaded face",
                      "comment": "Known fraud attempt",
                      "added_by": "api",
                      "reference_session_id": null,
                      "reference_session_number": null,
                      "reference_session_type": null,
                      "reference_object_uuid": "44444444-5555-6666-7777-888888888888",
                      "metadata": {
                        "reference_image_url": "https://media.example.com/faces/reference.jpg?expires=1760263938&signature=3f9a1c"
                      },
                      "created_at": "2026-10-12T10:12:18.904467Z"
                    }
                  },
                  "Sandbox application": {
                    "value": {
                      "uuid": "cccccccc-dddd-eeee-ffff-000000000000",
                      "value": "44444444-5555-6666-7777-888888888888",
                      "display_label": "Sandbox face entry",
                      "comment": "Known fraud attempt",
                      "added_by": "api",
                      "reference_session_id": null,
                      "reference_session_number": null,
                      "reference_session_type": null,
                      "reference_object_uuid": "44444444-5555-6666-7777-888888888888",
                      "metadata": {
                        "sandbox": true
                      },
                      "created_at": "2026-10-12T10:12:18.904467Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "La liste n'accepte pas les téléversements de visages, ou l'image est manquante, invalide, trop volumineuse ou ne présente aucun visage exploitable. Aucune entrée n'a été créée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not a face list": {
                    "value": {
                      "detail": "Face upload is only available for face-type lists."
                    }
                  },
                  "Custom face list": {
                    "value": {
                      "detail": "Face upload is only available for face blocklists and allowlists."
                    }
                  },
                  "Missing image": {
                    "value": {
                      "image": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid base64": {
                    "value": {
                      "image": [
                        "Invalid base64 encoding."
                      ]
                    }
                  },
                  "Too large": {
                    "value": {
                      "image": [
                        "Image exceeds maximum size of 2 MB."
                      ]
                    }
                  },
                  "Unreadable image": {
                    "value": {
                      "image": "Invalid image. Provide a valid base64-encoded JPG or PNG."
                    }
                  },
                  "No face": {
                    "value": {
                      "image": "No face detected in the image. Please upload a clear photo with a visible face."
                    }
                  },
                  "No usable face": {
                    "value": {
                      "image": "Could not extract face embedding. Try a different image."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: write` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no write access to workflows."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune liste avec cet UUID n'existe dans l'application de la clé API, ou elle a été supprimée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "List not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          },
          "503": {
            "description": "L'analyse faciale est temporairement indisponible. Aucune entrée n'a été créée ; réessayez plus tard.",
            "content": {
              "application/json": {
                "examples": {
                  "Unavailable": {
                    "value": {
                      "detail": "Service temporarily unavailable. Please try again later."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/blocklist/": {
      "get": {
        "summary": "Lister les éléments de la liste de blocage",
        "description": "Renvoie un flux paginé des visages, documents d'identité, numéros de téléphone et adresses e-mail des sessions de vérification de l'application qui sont actuellement sur liste de blocage, le `blocklisted_at` le plus récent en premier ; filtrez avec `item_type`. Les éléments des sessions supprimées ne sont pas inclus. Le flux couvre les enregistrements placés sur liste de blocage à partir d'une session (avec [Ajouter des éléments de session à la liste de blocage](https://docs.didit.me/fr/management-api/blocklist/add), depuis la console ou par une entrée de liste créée à partir d'une session) ; les valeurs ajoutées manuellement à une liste, les visages téléversés, les visages issus d'un selfie de capture de document et les autres types d'entrées sont lus avec [Répertorier les entrées de liste](https://docs.didit.me/fr/management-api/lists/list-entries). `face_image` et `front_image` sont des URL signées à courte durée de vie, et une clé API restreinte sans `media: read` reçoit `null`. Une clé API restreinte nécessite `workflows: read`.",
        "operationId": "list_blocklist_items",
        "x-didit-sdk": {
          "resource": "blocklist",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Blocklist"
        ],
        "parameters": [
          {
            "name": "item_type",
            "in": "query",
            "required": false,
            "description": "Uniquement les éléments de ce type. Lorsqu'il est omis, tous les types sont renvoyés.",
            "schema": {
              "type": "string",
              "enum": [
                "face",
                "document",
                "phone",
                "email"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Taille de page. Vaut 50 par défaut. Une valeur supérieure à 1000000 renvoie `400` ; une valeur égale à zéro, négative ou non numérique repasse par défaut à 50.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Indice de départ (base zéro) du premier élément à retourner. Privilégiez l'utilisation de `next`. Une valeur supérieure à 1000000 retourne `400` ; une valeur négative ou non numérique revient par défaut à 0.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/blocklist/?item_type=document' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.blocklist.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.blocklist.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Blocklist.ListAutoPaging(ctx, didit.BlocklistListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.blocklist().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->blocklist->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.blocklist.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Blocklist.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page d'éléments sur liste de blocage, les plus récents en premier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Nombre total d'éléments de liste de blocage correspondant aux filtres."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BlocklistedItem"
                      }
                    }
                  }
                },
                "examples": {
                  "Mixed feed": {
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "type": "document",
                          "session_id": "33333333-4444-5555-6666-777777777777",
                          "session_number": 1042,
                          "blocklisted_at": "2026-10-12T10:06:12.701553Z",
                          "face_image": null,
                          "document_type": "ID",
                          "document_number": "X1234567",
                          "front_image": "https://media.example.com/documents/front.jpg?expires=1760263938&signature=8b2e47",
                          "phone_number": null,
                          "country_code": null,
                          "email": null
                        },
                        {
                          "type": "phone",
                          "session_id": "77777777-8888-9999-0000-111111111111",
                          "session_number": 1017,
                          "blocklisted_at": "2026-10-08T15:31:09.400127Z",
                          "face_image": null,
                          "document_type": null,
                          "document_number": null,
                          "front_image": null,
                          "phone_number": "+14155552671",
                          "country_code": "US",
                          "email": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Un paramètre de requête est invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown item type": {
                    "value": {
                      "item_type": [
                        "\"wallet\" is not a valid choice."
                      ]
                    }
                  },
                  "Limit too large": {
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: read` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no read access to workflows."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "La limite de lecture partagée de 600 requêtes par minute et par clé API a été dépassée. Respectez l'en-tête `Retry-After` avant de réessayer.",
            "content": {
              "application/json": {
                "examples": {
                  "Rate limited": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/blocklist/add/": {
      "post": {
        "summary": "Ajouter des éléments de la session à la liste de blocage",
        "description": "Ajoute le visage, le document d'identité, le numéro de téléphone ou l'adresse e-mail d'une session de vérification d'une personne de l'application à la liste de blocage. Pour chaque type sélectionné, Didit récupère l'enregistrement le plus récent de la session, le marque comme bloqué et ajoute une entrée liée à la session à la liste de blocage correspondante du système (`added_by: \"api\"`), de sorte que les nouvelles sessions présentant un visage, un numéro de document, un numéro de téléphone ou une adresse e-mail correspondant soient refusées. Chaque élément sélectionné est d'abord vérifié : si l'un d'eux est manquant, rien n'est ajouté à la liste de blocage ; répéter l'appel pour un élément déjà répertorié conserve son entrée unique et actualise `blocklisted_at`. La session elle-même et les sessions déjà terminées ne sont pas modifiées. Une clé API restreinte nécessite `workflows: write`.",
        "operationId": "add_to_blocklist",
        "x-didit-sdk": {
          "resource": "blocklist",
          "method": "add",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Blocklist"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "session_id"
                ],
                "description": "Au moins un indicateur `blocklist_*` doit être `true`.",
                "properties": {
                  "session_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Une session de vérification d'utilisateur de votre application. Les sessions supprimées sont refusées."
                  },
                  "blocklist_face": {
                    "type": "boolean",
                    "default": false,
                    "description": "Ajouter le visage de la session à la liste de blocage."
                  },
                  "blocklist_document": {
                    "type": "boolean",
                    "default": false,
                    "description": "Ajouter le document d'identité de la session à la liste de blocage. Le document requiert son pays de délivrance, son type de document, son numéro de document et son nom complet."
                  },
                  "blocklist_phone": {
                    "type": "boolean",
                    "default": false,
                    "description": "Ajouter le numéro de téléphone de la session à la liste de blocage."
                  },
                  "blocklist_email": {
                    "type": "boolean",
                    "default": false,
                    "description": "Ajouter l'adresse e-mail de la session à la liste de blocage."
                  }
                }
              },
              "examples": {
                "Face and document": {
                  "value": {
                    "session_id": "33333333-4444-5555-6666-777777777777",
                    "blocklist_face": true,
                    "blocklist_document": true
                  }
                },
                "Phone only": {
                  "value": {
                    "session_id": "33333333-4444-5555-6666-777777777777",
                    "blocklist_phone": true
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/blocklist/add/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"session_id\": \"33333333-4444-5555-6666-777777777777\",\n    \"blocklist_face\": true,\n    \"blocklist_document\": true\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.blocklist.add(\n    session_id=\"33333333-4444-5555-6666-777777777777\",\n    blocklist_face=True,\n    blocklist_document=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.blocklist.add({\n  session_id: \"33333333-4444-5555-6666-777777777777\",\n  blocklist_face: true,\n  blocklist_document: true,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Blocklist.Add(ctx, didit.BlocklistAddParams{\n\tSessionID:         \"33333333-4444-5555-6666-777777777777\",\n\tBlocklistFace:     didit.Bool(true),\n\tBlocklistDocument: didit.Bool(true),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.BlocklistAddParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.blocklist().add(BlocklistAddParams.builder()\n        .sessionId(\"33333333-4444-5555-6666-777777777777\")\n        .blocklistFace(true)\n        .blocklistDocument(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->blocklist->add([\n    'session_id' => '33333333-4444-5555-6666-777777777777',\n    'blocklist_face' => true,\n    'blocklist_document' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.blocklist.add(\n  session_id: \"33333333-4444-5555-6666-777777777777\",\n  blocklist_face: true,\n  blocklist_document: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Blocklist.AddAsync(new BlocklistAddParams\n{\n    SessionId = \"33333333-4444-5555-6666-777777777777\",\n    BlocklistFace = true,\n    BlocklistDocument = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Les éléments sélectionnés ont été ajoutés à la liste de blocage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Toujours `Successfully updated blocklist.`"
                    }
                  }
                },
                "examples": {
                  "Blocklisted": {
                    "value": {
                      "message": "Successfully updated blocklist."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le corps est invalide, la session n'est pas une session de vérification de cette application, ou elle ne possède aucun enregistrement du type sélectionné. Rien n'a été ajouté à la liste de blocage.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown session": {
                    "value": {
                      "non_field_errors": [
                        "Session not found"
                      ]
                    }
                  },
                  "No item selected": {
                    "value": {
                      "non_field_errors": [
                        "Must specify at least one item to blocklist"
                      ]
                    }
                  },
                  "No face record": {
                    "value": {
                      "non_field_errors": [
                        "Session does not have a face record"
                      ]
                    }
                  },
                  "Incomplete document": {
                    "value": {
                      "non_field_errors": [
                        "To blocklist a document, the document must have an issuing state, document type, document number and full name"
                      ]
                    }
                  },
                  "Invalid session id": {
                    "value": {
                      "session_id": [
                        "Must be a valid UUID."
                      ]
                    }
                  },
                  "Missing session id": {
                    "value": {
                      "session_id": [
                        "This field is required."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: write` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no write access to workflows."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/blocklist/remove/": {
      "post": {
        "summary": "Retirer les éléments de la session de la liste de blocage",
        "description": "Lève le blocage sur le visage, le document d'identité, le numéro de téléphone ou l'adresse e-mail d'une session de vérification de personne de l'application. Pour chaque type sélectionné, Didit prend l'enregistrement le plus récent de la session, retire son indicateur de mise sur liste de blocage et supprime les entrées de liste de blocage système créées à partir de cet enregistrement, afin qu'il ne refuse plus de nouvelles sessions. Les entrées ajoutées à une liste par valeur ne sont pas modifiées : retrouvez-les avec [List list entries](https://docs.didit.me/fr/management-api/lists/list-entries) et supprimez-les avec [Delete a list entry](https://docs.didit.me/fr/management-api/lists/delete-entry). Débloquer un enregistrement qui n'est pas sur liste de blocage réussit et ne modifie rien, et les sessions déjà terminées ne sont pas modifiées. Une clé API restreinte nécessite `workflows: write`.",
        "operationId": "remove_from_blocklist",
        "x-didit-sdk": {
          "resource": "blocklist",
          "method": "remove",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Blocklist"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "session_id"
                ],
                "description": "Au moins un indicateur `unblock_*` doit être `true`.",
                "properties": {
                  "session_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Une session de vérification d'utilisateur de votre application. Les sessions supprimées sont refusées."
                  },
                  "unblock_face": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lever le blocage sur le visage de la session."
                  },
                  "unblock_document": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lever le blocage sur le document d'identité de la session."
                  },
                  "unblock_phone": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lever le blocage sur le numéro de téléphone de la session."
                  },
                  "unblock_email": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lever le blocage sur l'adresse e-mail de la session."
                  }
                }
              },
              "examples": {
                "Face and document": {
                  "value": {
                    "session_id": "33333333-4444-5555-6666-777777777777",
                    "unblock_face": true,
                    "unblock_document": true
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/blocklist/remove/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"session_id\": \"33333333-4444-5555-6666-777777777777\",\n    \"unblock_face\": true,\n    \"unblock_document\": true\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.blocklist.remove(\n    session_id=\"33333333-4444-5555-6666-777777777777\",\n    unblock_face=True,\n    unblock_document=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.blocklist.remove({\n  session_id: \"33333333-4444-5555-6666-777777777777\",\n  unblock_face: true,\n  unblock_document: true,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Blocklist.Remove(ctx, didit.BlocklistRemoveParams{\n\tSessionID:       \"33333333-4444-5555-6666-777777777777\",\n\tUnblockFace:     didit.Bool(true),\n\tUnblockDocument: didit.Bool(true),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.BlocklistRemoveParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.blocklist().remove(BlocklistRemoveParams.builder()\n        .sessionId(\"33333333-4444-5555-6666-777777777777\")\n        .unblockFace(true)\n        .unblockDocument(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->blocklist->remove([\n    'session_id' => '33333333-4444-5555-6666-777777777777',\n    'unblock_face' => true,\n    'unblock_document' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.blocklist.remove(\n  session_id: \"33333333-4444-5555-6666-777777777777\",\n  unblock_face: true,\n  unblock_document: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Blocklist.RemoveAsync(new BlocklistRemoveParams\n{\n    SessionId = \"33333333-4444-5555-6666-777777777777\",\n    UnblockFace = true,\n    UnblockDocument = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le blocage sur les éléments sélectionnés a été levé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Toujours `Successfully removed from blocklist.`"
                    }
                  }
                },
                "examples": {
                  "Unblocked": {
                    "value": {
                      "message": "Successfully removed from blocklist."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le corps est invalide, la session n'est pas une session de vérification de cette application, ou elle ne possède aucun enregistrement du type sélectionné. Rien n'a été modifié.",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown session": {
                    "value": {
                      "non_field_errors": [
                        "Session not found"
                      ]
                    }
                  },
                  "No item selected": {
                    "value": {
                      "non_field_errors": [
                        "Must specify at least one item to unblock"
                      ]
                    }
                  },
                  "No email record": {
                    "value": {
                      "non_field_errors": [
                        "Session does not have an email record"
                      ]
                    }
                  },
                  "Invalid session id": {
                    "value": {
                      "session_id": [
                        "Must be a valid UUID."
                      ]
                    }
                  },
                  "Missing session id": {
                    "value": {
                      "session_id": [
                        "This field is required."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Les autres échecs d'authentification renvoient `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `x-api-key` est manquant (une clé incorrecte, révoquée ou expirée renvoie `401`), ou une clé API restreinte n'a pas l'autorisation `workflows: write` ou est utilisée depuis une adresse IP hors de sa liste d'autorisation.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without workflows access": {
                    "value": {
                      "detail": "This API key has no write access to workflows."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/webhook/": {
      "get": {
        "summary": "Obtenir la configuration du webhook",
        "description": "Renvoie les paramètres de webhook de l'application en un seul appel : chaque [destination de webhook](https://docs.didit.me/fr/management-api/webhook/list-destinations) avec son secret de signature, les types d'événements auxquels une destination peut s'abonner, l'URL, la version et le secret de webhook au niveau de l'application (hérité), la politique de conservation des données et des gabarits biométriques, ainsi que les hôtes de retour de portefeuille Digital ID. Didit remet les webhooks aux destinations, chacun étant signé avec son propre `secret_shared_key` ; les champs de premier niveau `webhook_url`, `webhook_version` et `secret_shared_key` ne sont utilisés que lorsqu'aucune destination n'est activée, et alors uniquement pour `status.updated` et `data.updated`. La réponse contient des secrets de signature, veillez donc à ne l'inclure ni dans les journaux ni dans le code côté client. Une clé API avec portée nécessite `webhooks: read`.",
        "operationId": "get_webhook_config",
        "x-didit-sdk": {
          "resource": "webhooks",
          "method": "retrieve_config",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/webhook/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.retrieve_config()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.retrieveConfig();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Webhooks.RetrieveConfig(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().retrieveConfig();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->retrieveConfig();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.webhooks.retrieve_config\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.RetrieveConfigAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La configuration du webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookConfig"
                },
                "examples": {
                  "One destination": {
                    "value": {
                      "webhook_url": "https://yourapp.com/webhooks/didit",
                      "webhook_version": "v3",
                      "secret_shared_key": "dGhpcy1pcy10aGUtYXBwLWxldmVsLXNlY3JldC0wMDA",
                      "capture_method": "MOBILE",
                      "data_retention_months": 24,
                      "face_retention_policy": "delete_with_session",
                      "face_retention_days": null,
                      "biometric_consent_mode": "auto",
                      "available_events": [
                        {
                          "value": "status.updated",
                          "label": "Session status updated"
                        },
                        {
                          "value": "data.updated",
                          "label": "Session data updated"
                        },
                        {
                          "value": "user.status.updated",
                          "label": "User status updated"
                        },
                        {
                          "value": "user.data.updated",
                          "label": "User data updated"
                        },
                        {
                          "value": "business.status.updated",
                          "label": "Business status updated"
                        },
                        {
                          "value": "business.data.updated",
                          "label": "Business data updated"
                        },
                        {
                          "value": "activity.created",
                          "label": "Activity created"
                        },
                        {
                          "value": "transaction.created",
                          "label": "Transaction created"
                        },
                        {
                          "value": "transaction.status.updated",
                          "label": "Transaction status updated"
                        },
                        {
                          "value": "travel_rule.status.updated",
                          "label": "Travel Rule Status Updated"
                        },
                        {
                          "value": "workflow.compliance_changed",
                          "label": "Workflow Compliance Changed"
                        }
                      ],
                      "allowed_return_hosts": [
                        "shop.example.com"
                      ],
                      "endpoints": [
                        {
                          "uuid": "11111111-2222-3333-4444-555555555555",
                          "label": "Production session webhooks",
                          "url": "https://yourapp.com/webhooks/didit",
                          "enabled": true,
                          "webhook_version": "v3",
                          "secret_shared_key": "dGhpcy1pcy1hbi1leGFtcGxlLXNlY3JldC0wMDAwMDA",
                          "subscribed_events": [
                            "status.updated",
                            "data.updated"
                          ],
                          "created_at": "2026-01-04T08:00:00.000000Z",
                          "updated_at": "2026-04-22T14:09:11.523671Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Un en-tête `x-api-key` manquant, invalide ou révoqué renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without webhooks read": {
                    "value": {
                      "detail": "This API key has no read access to webhooks."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 600 requêtes GET dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (600).",
                "schema": {
                  "type": "integer",
                  "example": 600
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-get"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Mettre à jour la configuration du webhook",
        "description": "Mettre à jour partiellement les paramètres au niveau de l'application : l'URL, la version et le secret de l'ancien webhook, la politique de conservation des données et des gabarits biométriques, ainsi que les hôtes de retour du portefeuille Digital ID. Envoyez uniquement les champs à modifier ; la réponse est la configuration complète, sous la même forme que `GET /v3/webhook/`. Les destinations ne sont pas gérées ici : créez-les, mettez-les à jour et supprimez-les avec les endpoints `/v3/webhook/destinations/`, et n'envoyez pas de champ `endpoints` à cet endpoint. Une modification de `data_retention_months` s'applique également aux sessions existantes, et les sessions qu'elle supprime ne peuvent pas être restaurées ; lisez d'abord [Conservation des données](https://docs.didit.me/fr/console/data-retention). Une clé API avec restriction de portée nécessite `webhooks: write`.",
        "operationId": "update_webhook_config",
        "x-didit-sdk": {
          "resource": "webhooks",
          "method": "update_config",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Envoyez uniquement les champs à modifier. Les destinations ne sont pas gérées ici.",
                "properties": {
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "nullable": true,
                    "maxLength": 2000,
                    "description": "URL de webhook au niveau de l'application obsolète. Didit l'utilise uniquement tant que l'application n'a aucune destination activée, et seulement pour `status.updated` et `data.updated`. Cela ne crée pas de destination, et la prochaine création, mise à jour ou suppression d'une destination la remplace. Pour recevoir des webhooks, créez plutôt une destination avec `POST /v3/webhook/destinations/`."
                  },
                  "webhook_version": {
                    "type": "string",
                    "enum": [
                      "v1",
                      "v2",
                      "v3"
                    ],
                    "description": "Version du payload de l'ancien `webhook_url`."
                  },
                  "rotate_secret_key": {
                    "type": "boolean",
                    "default": false,
                    "description": "`true` remplace immédiatement la valeur `secret_shared_key` au niveau de l'application par une nouvelle valeur aléatoire ; la nouvelle valeur figure dans la réponse. Les secrets des destinations ne sont pas modifiés. Chaque appel avec `true` génère un nouveau secret, il n'est donc pas idempotent."
                  },
                  "capture_method": {
                    "type": "string",
                    "enum": [
                      "MOBILE",
                      "MOBILE_AND_DESKTOP"
                    ],
                    "description": "Paramètre d'application obsolète. Le workflow de vérification ne le lit pas."
                  },
                  "data_retention_months": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "maximum": 120,
                    "description": "Fenêtre de suppression automatique en mois (un mois compte pour 30 jours), ou `null` pour aucune suppression automatique. Une modification s'applique également aux sessions existantes : chaque session de vérification d'un utilisateur plus ancienne que la nouvelle période est supprimée automatiquement, et cette suppression est irréversible."
                  },
                  "face_retention_policy": {
                    "type": "string",
                    "enum": [
                      "delete_with_session",
                      "retain_until_user_deleted"
                    ],
                    "description": "Ce qui advient de l'embedding facial d'une session lorsque la session est supprimée. `retain_until_user_deleted` nécessite `face_retention_days` dans la même requête ou déjà défini. Une modification s'applique aux suppressions de session à partir de ce moment ; elle ne crée ni ne purge aucun gabarit biométrique existant."
                  },
                  "face_retention_days": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 1,
                    "maximum": 3650,
                    "description": "Durée de conservation, en jours, des gabarits biométriques sous `retain_until_user_deleted`."
                  },
                  "biometric_consent_mode": {
                    "type": "string",
                    "enum": [
                      "auto",
                      "always",
                      "never"
                    ],
                    "description": "Moment où le flux hébergé et les SDK natifs demandent à la personne son consentement biométrique explicite avant une capture faciale. `auto` (par défaut) ne le demande que lorsqu'un déclencheur s'applique : un État déclaré, l'IP de la personne ou l'émetteur du document d'identité se trouve dans l'Illinois, au Texas ou au Colorado, ou la personne semble être aux États-Unis sans État connu. `always` le demande à chaque personne dont le workflow capture un visage. `never` n'affiche jamais l'étape, et vous recueillez vous-même le consentement avant le selfie. Chaque modification est enregistrée dans le journal d'audit. Voir [Consentement biométrique](https://docs.didit.me/fr/getting-started/biometric-consent)."
                  },
                  "allowed_return_hosts": {
                    "type": "array",
                    "maxItems": 20,
                    "description": "Remplace l'ensemble de la liste des hôtes de redirection pour le portefeuille Digital ID. Noms d'hôte simples uniquement, par exemple `shop.example.com` : pas de protocole, port, chemin ni caractère générique. Les valeurs sont converties en minuscules et les doublons sont supprimés. Envoyez `[]` pour vider la liste.",
                    "items": {
                      "type": "string",
                      "maxLength": 253
                    }
                  },
                  "allowed_domains": {
                    "type": "array",
                    "maxItems": 50,
                    "items": {
                      "type": "string",
                      "maxLength": 300
                    },
                    "description": "Remplace l'ensemble de la liste des origines autorisées. Origines (par exemple `https://app.example.com` ; `http` uniquement pour `localhost`) au sein desquelles le flux de vérification hébergé peut être intégré et vers lesquelles il peut rediriger l'utilisateur avec un rappel de session. Les appels de serveur à serveur ne sont pas affectés. Une liste vide signifie qu'aucune restriction n'est appliquée. Didit enregistre chaque origine en minuscules sans port par défaut. Une entrée non valide échoue avec une erreur `400` sur `allowed_domains`. Envoyez `[]` pour supprimer la restriction.",
                    "example": [
                      "https://app.example.com"
                    ]
                  }
                }
              },
              "examples": {
                "Enable biometric template retention": {
                  "value": {
                    "face_retention_policy": "retain_until_user_deleted",
                    "face_retention_days": 365,
                    "biometric_consent_mode": "auto"
                  }
                },
                "Rotate the legacy secret": {
                  "value": {
                    "rotate_secret_key": true
                  }
                },
                "Set data retention": {
                  "value": {
                    "data_retention_months": 24
                  }
                },
                "Register return hosts": {
                  "value": {
                    "allowed_return_hosts": [
                      "shop.example.com",
                      "app.example.com"
                    ]
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/webhook/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"face_retention_policy\": \"retain_until_user_deleted\", \"face_retention_days\": 365}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.update_config(\n    face_retention_policy=\"retain_until_user_deleted\",\n    face_retention_days=365,\n    biometric_consent_mode=\"auto\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.updateConfig({\n  face_retention_policy: \"retain_until_user_deleted\",\n  face_retention_days: 365,\n  biometric_consent_mode: \"auto\",\n});\nconsole.log(result);"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.WebhooksUpdateConfigParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().updateConfig(WebhooksUpdateConfigParams.builder()\n        .faceRetentionPolicy(WebhooksUpdateConfigParams.FaceRetentionPolicy.of(\"retain_until_user_deleted\"))\n        .faceRetentionDays(365L)\n        .biometricConsentMode(WebhooksUpdateConfigParams.BiometricConsentMode.of(\"auto\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->updateConfig([\n    'face_retention_policy' => 'retain_until_user_deleted',\n    'face_retention_days' => 365,\n    'biometric_consent_mode' => 'auto',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.webhooks.update_config(\n  face_retention_policy: \"retain_until_user_deleted\",\n  face_retention_days: 365,\n  biometric_consent_mode: \"auto\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.UpdateConfigAsync(new WebhooksUpdateConfigParams\n{\n    FaceRetentionPolicy = new WebhooksUpdateConfigParamsFaceRetentionPolicy(\"retain_until_user_deleted\"),\n    FaceRetentionDays = 365,\n    BiometricConsentMode = new WebhooksUpdateConfigParamsBiometricConsentMode(\"auto\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La configuration complète après la mise à jour, sous la même forme que `GET /v3/webhook/`. Si vous avez renouvelé le secret, enregistrez la nouvelle `secret_shared_key` avant d'écarter la réponse.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookConfig"
                },
                "examples": {
                  "Retention enabled": {
                    "value": {
                      "webhook_url": "https://yourapp.com/webhooks/didit",
                      "webhook_version": "v3",
                      "secret_shared_key": "dGhpcy1pcy10aGUtYXBwLWxldmVsLXNlY3JldC0wMDA",
                      "capture_method": "MOBILE",
                      "data_retention_months": 24,
                      "face_retention_policy": "retain_until_user_deleted",
                      "face_retention_days": 365,
                      "biometric_consent_mode": "auto",
                      "available_events": [
                        {
                          "value": "status.updated",
                          "label": "Session status updated"
                        },
                        {
                          "value": "data.updated",
                          "label": "Session data updated"
                        },
                        {
                          "value": "user.status.updated",
                          "label": "User status updated"
                        },
                        {
                          "value": "user.data.updated",
                          "label": "User data updated"
                        },
                        {
                          "value": "business.status.updated",
                          "label": "Business status updated"
                        },
                        {
                          "value": "business.data.updated",
                          "label": "Business data updated"
                        },
                        {
                          "value": "activity.created",
                          "label": "Activity created"
                        },
                        {
                          "value": "transaction.created",
                          "label": "Transaction created"
                        },
                        {
                          "value": "transaction.status.updated",
                          "label": "Transaction status updated"
                        },
                        {
                          "value": "travel_rule.status.updated",
                          "label": "Travel Rule Status Updated"
                        },
                        {
                          "value": "workflow.compliance_changed",
                          "label": "Workflow Compliance Changed"
                        }
                      ],
                      "allowed_return_hosts": [
                        "shop.example.com"
                      ],
                      "endpoints": [
                        {
                          "uuid": "11111111-2222-3333-4444-555555555555",
                          "label": "Production session webhooks",
                          "url": "https://yourapp.com/webhooks/didit",
                          "enabled": true,
                          "webhook_version": "v3",
                          "secret_shared_key": "dGhpcy1pcy1hbi1leGFtcGxlLXNlY3JldC0wMDAwMDA",
                          "subscribed_events": [
                            "status.updated",
                            "data.updated"
                          ],
                          "created_at": "2026-01-04T08:00:00.000000Z",
                          "updated_at": "2026-04-22T14:09:11.523671Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Échec de la validation : chaque champ non valide est associé à une liste de messages, et rien n'est modifié. Un corps qui n'est pas un JSON valide renvoie `{\"detail\": \"JSON parse error - ...\"}`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Chaque champ invalide associé à une liste de messages.",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Retention days missing": {
                    "value": {
                      "face_retention_days": [
                        "A finite retention duration is required when face retention is enabled."
                      ],
                      "biometric_consent_mode": "auto"
                    }
                  },
                  "Retention window out of range": {
                    "value": {
                      "data_retention_months": [
                        "Ensure this value is less than or equal to 120."
                      ]
                    }
                  },
                  "Invalid return host": {
                    "value": {
                      "allowed_return_hosts": [
                        "'https://shop.example.com' is not a hostname. Register the bare host (e.g. shop.example.com): no scheme, port, path or wildcard."
                      ]
                    }
                  },
                  "Invalid choice": {
                    "value": {
                      "face_retention_policy": [
                        "\"forever\" is not a valid choice."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Un en-tête `x-api-key` manquant, invalide ou révoqué renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without webhooks write": {
                    "value": {
                      "detail": "This API key has no write access to webhooks."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 300 requêtes d'écriture (POST, PATCH, PUT, DELETE) dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (300).",
                "schema": {
                  "type": "integer",
                  "example": 300
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-write"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/webhook/destinations/{destination_uuid}/analytics/": {
      "get": {
        "summary": "Obtenir les analyses de la destination de webhook",
        "description": "Totaux de livraison, taux d'échec et temps de réponse pour une destination de webhook, sur l'ensemble de la période (`summary`) et par jour UTC (`points`). Chaque tentative compte comme une livraison : le premier envoi d'un événement, chaque [réessai](https://docs.didit.me/fr/integration/webhooks#politique-de-nouvelles-tentatives) automatique et chaque renvoi. Une livraison est considérée comme échouée lorsque son statut HTTP enregistré est supérieur ou égal à 400 ; les dépassements de délai (enregistrés en `504`) et les échecs de connexion (`503`) comptent donc comme des échecs ; une livraison encore en file d'attente n'est comptabilisée que dans `total_deliveries`. Les historiques de livraison sont disponibles pendant environ 30 jours. Une clé API limitée nécessite `webhooks: read`.",
        "operationId": "get_webhook_destination_analytics",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "retrieve_analytics",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "name": "destination_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la destination (le `uuid` renvoyé par `GET /v3/webhook/destinations/`).",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "description": "Premier jour UTC à inclure, au format `YYYY-MM-DD` (inclus). Omettez pour démarrer à partir de la livraison la plus ancienne disponible. `dateFrom` est accepté comme alias.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-10-01"
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "description": "Dernier jour UTC à inclure, au format `YYYY-MM-DD` (inclus). Ne doit pas être antérieur à `date_from`. `dateTo` est accepté en tant qu'alias.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-10-16"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/webhook/destinations/11111111-2222-3333-4444-555555555555/analytics/?date_from=2026-10-01&date_to=2026-10-16' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.destinations.retrieve_analytics(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.destinations.retrieveAnalytics(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Webhooks.Destinations.RetrieveAnalytics(ctx, \"11111111-2222-3333-4444-555555555555\", didit.WebhooksDestinationsRetrieveAnalyticsParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().destinations().retrieveAnalytics(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->destinations->retrieveAnalytics('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.webhooks.destinations.retrieve_analytics(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.Destinations.RetrieveAnalyticsAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Statistiques de livraison pour la destination.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "summary",
                    "points"
                  ],
                  "properties": {
                    "summary": {
                      "type": "object",
                      "description": "Totaux sur la plage demandée.",
                      "required": [
                        "total_deliveries",
                        "failed_deliveries",
                        "min_response_time_ms",
                        "avg_response_time_ms",
                        "max_response_time_ms",
                        "error_rate_percentage"
                      ],
                      "properties": {
                        "total_deliveries": {
                          "type": "integer",
                          "minimum": 0,
                          "description": "Tentatives de livraison, y compris celles en file d'attente."
                        },
                        "failed_deliveries": {
                          "type": "integer",
                          "minimum": 0,
                          "description": "Tentatives dont le statut HTTP enregistré est 400 ou supérieur."
                        },
                        "min_response_time_ms": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Tentative la plus rapide en millisecondes, ou `null` si aucune tentative n'a de durée enregistrée."
                        },
                        "avg_response_time_ms": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Durée moyenne de tentative en millisecondes, arrondie, ou `null` lorsqu'aucune tentative n'a de durée enregistrée."
                        },
                        "max_response_time_ms": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Tentative la plus lente en millisecondes, ou `null` si aucune tentative n'a de durée enregistrée."
                        },
                        "error_rate_percentage": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 100,
                          "description": "`failed_deliveries` / `total_deliveries` x 100, arrondi à un nombre entier. `0` lorsqu'il n'y a aucune livraison."
                        }
                      }
                    },
                    "points": {
                      "type": "array",
                      "description": "Une entrée par jour UTC ayant fait l'objet de livraisons, de la plus ancienne à la plus récente. Les jours sans livraison sont omis ; comblez les écarts avec des zéros lors de la génération de graphiques.",
                      "items": {
                        "type": "object",
                        "required": [
                          "date",
                          "total_deliveries",
                          "failed_deliveries",
                          "min_response_time_ms",
                          "avg_response_time_ms",
                          "max_response_time_ms"
                        ],
                        "properties": {
                          "date": {
                            "type": "string",
                            "format": "date",
                            "description": "Jour UTC, `YYYY-MM-DD`."
                          },
                          "total_deliveries": {
                            "type": "integer",
                            "minimum": 0,
                            "description": "Tentatives de livraison, y compris celles en file d'attente."
                          },
                          "failed_deliveries": {
                            "type": "integer",
                            "minimum": 0,
                            "description": "Tentatives dont le statut HTTP enregistré est 400 ou supérieur."
                          },
                          "min_response_time_ms": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Tentative la plus rapide en millisecondes, ou `null` si aucune tentative n'a de durée enregistrée."
                          },
                          "avg_response_time_ms": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Durée moyenne de tentative en millisecondes, arrondie, ou `null` lorsqu'aucune tentative n'a de durée enregistrée."
                          },
                          "max_response_time_ms": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Tentative la plus lente en millisecondes, ou `null` si aucune tentative n'a de durée enregistrée."
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Three days of deliveries": {
                    "value": {
                      "summary": {
                        "total_deliveries": 1250,
                        "failed_deliveries": 12,
                        "min_response_time_ms": 38,
                        "avg_response_time_ms": 164,
                        "max_response_time_ms": 5004,
                        "error_rate_percentage": 1
                      },
                      "points": [
                        {
                          "date": "2026-10-14",
                          "total_deliveries": 410,
                          "failed_deliveries": 0,
                          "min_response_time_ms": 38,
                          "avg_response_time_ms": 152,
                          "max_response_time_ms": 911
                        },
                        {
                          "date": "2026-10-15",
                          "total_deliveries": 395,
                          "failed_deliveries": 12,
                          "min_response_time_ms": 41,
                          "avg_response_time_ms": 190,
                          "max_response_time_ms": 5004
                        },
                        {
                          "date": "2026-10-16",
                          "total_deliveries": 445,
                          "failed_deliveries": 0,
                          "min_response_time_ms": 40,
                          "avg_response_time_ms": 151,
                          "max_response_time_ms": 1220
                        }
                      ]
                    }
                  },
                  "No deliveries in range": {
                    "value": {
                      "summary": {
                        "total_deliveries": 0,
                        "failed_deliveries": 0,
                        "min_response_time_ms": null,
                        "avg_response_time_ms": null,
                        "max_response_time_ms": null,
                        "error_rate_percentage": 0
                      },
                      "points": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`date_from` ou `date_to` n'est pas une date au format `YYYY-MM-DD`, ou `date_to` est antérieure à `date_from`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Chaque champ invalide associé à une liste de messages.",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Malformed date": {
                    "value": {
                      "date_from": [
                        "Date has wrong format. Use one of these formats instead: YYYY-MM-DD."
                      ]
                    }
                  },
                  "Reversed range": {
                    "value": {
                      "date_to": [
                        "date_to must be greater than or equal to date_from."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Un en-tête `x-api-key` manquant, invalide ou révoqué renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without webhooks read": {
                    "value": {
                      "detail": "This API key has no read access to webhooks."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune destination avec cet UUID n'existe pour l'application, ou elle a été supprimée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Destination not found": {
                    "value": {
                      "detail": "Webhook destination not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 600 requêtes GET dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (600).",
                "schema": {
                  "type": "integer",
                  "example": 600
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-get"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/webhook/destinations/{destination_uuid}/deliveries/": {
      "get": {
        "summary": "Lister les livraisons vers les destinations de webhook",
        "description": "Parcourez chaque tentative de livraison vers une destination de webhook, de la plus récente à la plus ancienne. Le premier envoi de chaque événement, chaque [nouvelle tentative](https://docs.didit.me/fr/integration/webhooks#politique-de-nouvelles-tentatives) automatique et chaque renvoi constituent des entrées distinctes. Les entrées indiquent le statut HTTP et le temps de réponse mais pas le payload : récupérez une livraison pour lire ses en-têtes et son corps. `count` est exact jusqu'à 100 et affiche 100 au-delà, suivez donc `next` jusqu'à ce qu'il soit `null`. Les historiques de livraison sont conservés environ 30 jours. Une clé API avec des autorisations restreintes requiert `webhooks: read` et `decisions: read` ; une clé limitée à certains workflows ou aux sessions approuvées ne peut pas utiliser cet endpoint.",
        "operationId": "list_webhook_destination_deliveries",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "list_deliveries",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "name": "destination_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la destination (le `uuid` renvoyé par `GET /v3/webhook/destinations/`).",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Nombre maximal de livraisons par page. Vaut par défaut 50. Une valeur qui n'est pas un entier positif revient à 50 ; une valeur supérieure à 1000000 renvoie `400`.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "example": 50
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Nombre de livraisons à ignorer. Vaut 0 par défaut. Privilégiez l'utilisation des URL `next` et `previous` de la réponse.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "example": 0
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "description": "Premier jour UTC à inclure, au format `YYYY-MM-DD` (inclus). Omettez pour démarrer à partir de la livraison la plus ancienne disponible. `dateFrom` est accepté comme alias.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-10-01"
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "description": "Dernier jour UTC à inclure, au format `YYYY-MM-DD` (inclus). Ne doit pas être antérieur à `date_from`. `dateTo` est accepté en tant qu'alias.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-10-16"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/webhook/destinations/11111111-2222-3333-4444-555555555555/deliveries/?limit=50&date_from=2026-10-01' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.webhooks.destinations.list_deliveries(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.webhooks.destinations.listDeliveries(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Webhooks.Destinations.ListDeliveriesAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.WebhooksDestinationsListDeliveriesParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.webhooks().destinations().listDeliveries(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->webhooks->destinations->listDeliveries('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.webhooks.destinations.list_deliveries(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Webhooks.Destinations.ListDeliveriesAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de livraisons, de la plus récente à la plus ancienne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Livraisons correspondantes, exactes jusqu'à 100 et plafonnées à 100 au-delà. Utilisez `next` pour savoir si d'autres pages existent."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDestinationDelivery"
                      }
                    }
                  }
                },
                "examples": {
                  "Failed delivery, its retry and a queued event": {
                    "value": {
                      "count": 3,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "66666666-7777-8888-9999-000000000003",
                          "session_id": null,
                          "request_url": "https://yourapp.com/webhooks/didit",
                          "response_status": null,
                          "response_time_ms": null,
                          "status": "APPROVED",
                          "webhook_type": "transaction.created",
                          "created_at": "2026-10-15T09:23:02.871190Z"
                        },
                        {
                          "uuid": "66666666-7777-8888-9999-000000000002",
                          "session_id": "22222222-3333-4444-5555-666666666666",
                          "request_url": "https://yourapp.com/webhooks/didit",
                          "response_status": 200,
                          "response_time_ms": 143,
                          "status": "In Progress",
                          "webhook_type": "status.updated",
                          "created_at": "2026-10-15T09:22:19.104233Z"
                        },
                        {
                          "uuid": "66666666-7777-8888-9999-000000000001",
                          "session_id": "22222222-3333-4444-5555-666666666666",
                          "request_url": "https://yourapp.com/webhooks/didit",
                          "response_status": 503,
                          "response_time_ms": 412,
                          "status": "In Progress",
                          "webhook_type": "status.updated",
                          "created_at": "2026-10-15T09:21:18.412345Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`date_from` ou `date_to` n'est pas une date au format `YYYY-MM-DD`, `date_to` est antérieure à `date_from`, ou `limit` ou `offset` est supérieur à 1000000 (cette erreur est un tableau de messages JSON).",
            "content": {
              "application/json": {
                "examples": {
                  "Malformed date": {
                    "value": {
                      "date_from": [
                        "Date has wrong format. Use one of these formats instead: YYYY-MM-DD."
                      ]
                    }
                  },
                  "Reversed range": {
                    "value": {
                      "date_to": [
                        "date_to must be greater than or equal to date_from."
                      ]
                    }
                  },
                  "Limit too large": {
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Un en-tête `x-api-key` manquant, invalide ou révoqué renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.` Une clé limitée à certains workflows ou à des sessions approuvées renvoie `This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint.`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without webhooks read": {
                    "value": {
                      "detail": "This API key has no read access to webhooks."
                    }
                  },
                  "Scoped key without decisions read": {
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune destination avec cet UUID n'existe pour l'application, ou elle a été supprimée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Destination not found": {
                    "value": {
                      "detail": "Webhook destination not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 600 requêtes GET dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (600).",
                "schema": {
                  "type": "integer",
                  "example": 600
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-get"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/webhook/destinations/{destination_uuid}/deliveries/{delivery_uuid}/": {
      "get": {
        "summary": "Obtenir la livraison de la destination de webhook",
        "description": "Récupérer une tentative de livraison vers une destination de webhook avec les en-têtes de requête exacts et le corps JSON envoyés par Didit, le statut HTTP renvoyé par votre endpoint et le temps de réponse. `request_header` et `request_body` sont du texte JSON : analysez-les pour lire les en-têtes de signature et le payload, par exemple pour vérifier votre [vérification de signature](https://docs.didit.me/fr/integration/webhooks#vérification-de-la-signature) par rapport au `secret_shared_key` de la destination. Une livraison ne contient jamais le secret de signature, et Didit n'enregistre pas le corps de réponse de votre endpoint. Une clé API avec restriction de portée nécessite `webhooks: read` et `decisions: read` ; une clé limitée à certains workflows ou aux sessions approuvées ne peut pas utiliser cet endpoint.",
        "operationId": "get_webhook_destination_delivery",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "retrieve_delivery",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "name": "destination_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la destination à laquelle la livraison a été envoyée.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "delivery_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la livraison : le `uuid` d'une entrée renvoyée par `GET /v3/webhook/destinations/{destination_uuid}/deliveries/`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "66666666-7777-8888-9999-000000000001"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/webhook/destinations/11111111-2222-3333-4444-555555555555/deliveries/66666666-7777-8888-9999-000000000001/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.destinations.retrieve_delivery(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"66666666-7777-8888-9999-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.destinations.retrieveDelivery(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"66666666-7777-8888-9999-000000000001\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Webhooks.Destinations.RetrieveDelivery(ctx, \"11111111-2222-3333-4444-555555555555\", \"66666666-7777-8888-9999-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().destinations().retrieveDelivery(\"11111111-2222-3333-4444-555555555555\", \"66666666-7777-8888-9999-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->destinations->retrieveDelivery('11111111-2222-3333-4444-555555555555', '66666666-7777-8888-9999-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.webhooks.destinations.retrieve_delivery(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"66666666-7777-8888-9999-000000000001\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.Destinations.RetrieveDeliveryAsync(\"11111111-2222-3333-4444-555555555555\", \"66666666-7777-8888-9999-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La livraison, avec ses en-têtes et son corps de requête.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDestinationDeliveryDetail"
                },
                "examples": {
                  "Connection failure": {
                    "value": {
                      "uuid": "66666666-7777-8888-9999-000000000001",
                      "session_id": "22222222-3333-4444-5555-666666666666",
                      "request_url": "https://yourapp.com/webhooks/didit",
                      "response_status": 503,
                      "response_time_ms": 412,
                      "status": "In Progress",
                      "webhook_type": "status.updated",
                      "created_at": "2026-10-15T09:21:18.412345Z",
                      "request_header": "{\"Content-Type\": \"application/json\", \"X-Signature\": \"a5e02a03404e1337a0198e6be15d34abbd053c658a0e51e5d0e78554213ef29b\", \"X-Signature-V2\": \"927e7cb770c94ce745939bff73f04aa200015f3bc64795ba46c2aaf78a6cedc5\", \"X-Signature-Simple\": \"e37b0d4c716c72bb5ae7127b9cc455d28ab4686e9e22312b4ec2327409a73302\", \"X-Timestamp\": \"1792056078\", \"User-Agent\": \"DiditWebhook/2.0 +https://didit.me\"}",
                      "request_body": "{\"application_id\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"created_at\":1792056057,\"environment\":\"live\",\"event_id\":\"33333333-4444-5555-6666-777777777777\",\"sandbox_scenario\":null,\"session_id\":\"22222222-3333-4444-5555-666666666666\",\"status\":\"In Progress\",\"timestamp\":1792056078,\"vendor_data\":\"user-123\",\"webhook_type\":\"status.updated\",\"workflow_id\":\"44444444-5555-6666-7777-888888888888\",\"workflow_version\":3}"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Un en-tête `x-api-key` manquant, invalide ou révoqué renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.` Une clé limitée à certains workflows ou à des sessions approuvées renvoie `This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint.`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without webhooks read": {
                    "value": {
                      "detail": "This API key has no read access to webhooks."
                    }
                  },
                  "Scoped key without decisions read": {
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La destination n'existe pas pour l'application ou a été supprimée, ou la livraison n'existe pas, appartient à une autre destination, ou n'est plus disponible.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Destination not found": {
                    "value": {
                      "detail": "Webhook destination not found."
                    }
                  },
                  "Delivery not found": {
                    "value": {
                      "detail": "Webhook delivery not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 600 requêtes GET dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (600).",
                "schema": {
                  "type": "integer",
                  "example": 600
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-get"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/webhook/destinations/{destination_uuid}/deliveries/{delivery_uuid}/resend/": {
      "post": {
        "summary": "Renvoyer la livraison vers la destination de webhook",
        "description": "Renvoyez une livraison passée, par exemple après une indisponibilité de votre endpoint. Didit prend le payload stocké, lui attribue un nouveau `timestamp`, le signe à nouveau avec le `secret_shared_key` actuel de la destination (`X-Signature`, `X-Signature-V2`, `X-Signature-Simple` et `X-Timestamp`) et l'envoie à l'URL `request_url` de la livraison, même si l'URL de la destination a changé depuis ou si la destination est désactivée. `event_id` et le reste du payload sont inchangés, vous devez donc dédupliquer sur `event_id`. L'appel attend votre endpoint jusqu'à 5 secondes et renvoie la nouvelle livraison avec `200` quelle que soit la réponse de votre endpoint : lisez `response_status`. Un renvoi n'est pas réessayé automatiquement, chaque appel effectue un nouvel envoi et crée une nouvelle livraison, et la requête n'a pas de corps. Une clé API restreinte nécessite `webhooks: write` et `decisions: read` ; une clé limitée à certains workflows ou aux sessions approuvées ne peut pas utiliser cet endpoint.",
        "operationId": "resend_webhook_destination_delivery",
        "x-didit-sdk": {
          "resource": "webhooks.destinations",
          "method": "resend_delivery",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "name": "destination_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la destination à laquelle la livraison a été envoyée.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "delivery_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la livraison à renvoyer : le `uuid` d'une entrée renvoyée par `GET /v3/webhook/destinations/{destination_uuid}/deliveries/`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "66666666-7777-8888-9999-000000000001"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/webhook/destinations/11111111-2222-3333-4444-555555555555/deliveries/66666666-7777-8888-9999-000000000001/resend/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.webhooks.destinations.resend_delivery(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"66666666-7777-8888-9999-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.webhooks.destinations.resendDelivery(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"66666666-7777-8888-9999-000000000001\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Webhooks.Destinations.ResendDelivery(ctx, \"11111111-2222-3333-4444-555555555555\", \"66666666-7777-8888-9999-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.webhooks().destinations().resendDelivery(\"11111111-2222-3333-4444-555555555555\", \"66666666-7777-8888-9999-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->webhooks->destinations->resendDelivery('11111111-2222-3333-4444-555555555555', '66666666-7777-8888-9999-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.webhooks.destinations.resend_delivery(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"66666666-7777-8888-9999-000000000001\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Webhooks.Destinations.ResendDeliveryAsync(\"11111111-2222-3333-4444-555555555555\", \"66666666-7777-8888-9999-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La nouvelle livraison, déjà tentée. `response_status` est ce que votre endpoint a répondu cette fois-ci (`504` délai d'expiration, `503` échec de connexion). La livraison d'origine reste inchangée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDestinationDeliveryDetail"
                },
                "examples": {
                  "Accepted on resend": {
                    "value": {
                      "uuid": "66666666-7777-8888-9999-000000000004",
                      "session_id": "22222222-3333-4444-5555-666666666666",
                      "request_url": "https://yourapp.com/webhooks/didit",
                      "response_status": 200,
                      "response_time_ms": 151,
                      "status": "In Progress",
                      "webhook_type": "status.updated",
                      "created_at": "2026-10-16T14:05:42.330981Z",
                      "request_header": "{\"Content-Type\": \"application/json\", \"X-Signature\": \"b8eb1e376517ee0cad8ba98ff7f8fd35fc72eca231000963a96a335f82328835\", \"X-Signature-V2\": \"9efd2ce9ed1303e1d05273ef9608a59363ed9789a05253db4748b3e8e50cb109\", \"X-Signature-Simple\": \"bf3a9dc04b2c20ab539203b0cd5cca2a10f630bf62d8feb6d68d82af80f64774\", \"X-Timestamp\": \"1792159542\", \"User-Agent\": \"DiditWebhook/2.0 +https://didit.me\"}",
                      "request_body": "{\"application_id\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"created_at\":1792056057,\"environment\":\"live\",\"event_id\":\"33333333-4444-5555-6666-777777777777\",\"sandbox_scenario\":null,\"session_id\":\"22222222-3333-4444-5555-666666666666\",\"status\":\"In Progress\",\"timestamp\":1792159542,\"vendor_data\":\"user-123\",\"webhook_type\":\"status.updated\",\"workflow_id\":\"44444444-5555-6666-7777-888888888888\",\"workflow_version\":3}"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "La livraison enregistrée n'a pas pu être signée de nouveau. Rien n'est envoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    },
                    "code": {
                      "type": "string",
                      "description": "Code d'erreur stable lisible par machine. Effectuez vos branchements sur cette valeur, pas sur `detail`."
                    }
                  }
                },
                "examples": {
                  "Unsignable delivery": {
                    "value": {
                      "detail": "Invalid webhook data format",
                      "code": "invalid_webhook_payload"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Un en-tête `x-api-key` manquant, invalide ou révoqué renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.` Une clé limitée à certains workflows ou à des sessions approuvées renvoie `This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint.`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without webhooks write": {
                    "value": {
                      "detail": "This API key has no write access to webhooks."
                    }
                  },
                  "Scoped key without decisions read": {
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La destination n'existe pas pour l'application ou a été supprimée, ou la livraison n'existe pas, appartient à une autre destination, ou n'est plus disponible.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Destination not found": {
                    "value": {
                      "detail": "Webhook destination not found."
                    }
                  },
                  "Delivery not found": {
                    "value": {
                      "detail": "Webhook delivery not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 300 requêtes d'écriture (POST, PATCH, PUT, DELETE) dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (300).",
                "schema": {
                  "type": "integer",
                  "example": 300
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-write"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/events/": {
      "get": {
        "summary": "Lister les événements de surveillance",
        "description": "Lister les événements de surveillance stockés pour votre application, du `occurred_at` le plus récent au plus ancien, avec des filtres optionnels combinés par AND. Les filtres à valeurs multiples (`event_category`, `action_type`, `status`, `retention_class`) répètent le paramètre et correspondent à l'une des valeurs ; les autres filtres sont des correspondances exactes, et les valeurs inconnues ne renvoient simplement aucun événement. Chaque résultat est un résumé : appelez `GET /v3/events/{event_uuid}/` pour le payload, le contexte de l'appareil, l'enrichissement de l'IP et les éléments de preuve des règles, et préférez `GET /v3/events/subjects/{vendor_data}/` pour l'historique d'un seul sujet. Les lectures fonctionnent que l'ingestion d'événements soit activée ou non. Une clé API restreinte nécessite `transactions: read`. Voir [Ingestion d'événements](https://docs.didit.me/fr/transaction-monitoring/events).",
        "operationId": "list_monitoring_events",
        "x-didit-sdk": {
          "resource": "monitoring_events",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Monitoring Events"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Nombre maximal d'événements par page. Vaut par défaut 50. Les valeurs supérieures à 1000000 renvoient `400` ; une valeur non numérique, nulle ou négative revient à 50.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "example": 50
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Nombre d'événements à ignorer. Vaut 0 par défaut. Privilégiez l'utilisation de l'URL `next` de la réponse.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "example": 0
          },
          {
            "name": "event_category",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements appartenant à ces catégories. Répétez le paramètre pour plusieurs valeurs (`?event_category=payment&event_category=dispute`) ; un événement correspondant à l'une d'entre elles est renvoyé.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "auth",
                  "session",
                  "gameplay",
                  "bonus",
                  "affiliate",
                  "payment",
                  "dispute",
                  "security",
                  "responsible_gambling",
                  "custom"
                ]
              }
            },
            "example": [
              "payment",
              "dispute"
            ]
          },
          {
            "name": "action_type",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements associés à ces types d'actions (exacts, sensibles à la casse). Répétez pour plusieurs valeurs.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "example": [
              "deposit_completed",
              "chargeback_opened"
            ]
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements associés à ces statuts. Répétez pour plusieurs valeurs.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "ACCEPTED",
                  "APPROVED",
                  "IN_REVIEW",
                  "DECLINED"
                ]
              }
            },
            "example": [
              "IN_REVIEW",
              "DECLINED"
            ]
          },
          {
            "name": "retention_class",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements appartenant à ces classes de conservation. Répétez pour plusieurs valeurs.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "low_value",
                  "standard",
                  "risk_relevant",
                  "monetary_or_compliance"
                ]
              }
            },
            "example": [
              "risk_relevant"
            ]
          },
          {
            "name": "subject_vendor_data",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `vendor_data` du sujet. Le même identifiant peut désigner un individu et une entreprise ; ajoutez `subject_entity_type` pour en choisir un, ou utilisez `GET /v3/events/subjects/{vendor_data}/`.",
            "schema": {
              "type": "string"
            },
            "example": "user-42"
          },
          {
            "name": "subject_entity_type",
            "in": "query",
            "required": false,
            "description": "`company` ne renvoie que les événements des sujets correspondant à des entreprises ; toute autre valeur non vide (par exemple `individual`) ne renvoie que les événements des individus. Omettez-le pour renvoyer les deux.",
            "schema": {
              "type": "string",
              "enum": [
                "individual",
                "company"
              ]
            },
            "example": "individual"
          },
          {
            "name": "business_vendor_data",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `business.vendor_data` envoyé avec l'événement.",
            "schema": {
              "type": "string"
            },
            "example": "merchant-7"
          },
          {
            "name": "session_id",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur `session.session_id`.",
            "schema": {
              "type": "string"
            },
            "example": "web-session-abc"
          },
          {
            "name": "device_fingerprint",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur `device_context.fingerprint`.",
            "schema": {
              "type": "string"
            },
            "example": "fp-a8c1"
          },
          {
            "name": "ip_address",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur l'adresse IP de l'événement.",
            "schema": {
              "type": "string"
            },
            "example": "203.0.113.42"
          },
          {
            "name": "game_id",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `game_id` promu.",
            "schema": {
              "type": "string"
            },
            "example": "poker-holdem-01"
          },
          {
            "name": "round_id",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `round_id` promu.",
            "schema": {
              "type": "string"
            },
            "example": "round-88231"
          },
          {
            "name": "affiliate_code",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `affiliate_code` promu.",
            "schema": {
              "type": "string"
            },
            "example": "aff-summer"
          },
          {
            "name": "payment_reference_id",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur la référence de paiement (provenant de `transaction_context.payment_reference_id` ou de `payload.payment_reference_id`).",
            "schema": {
              "type": "string"
            },
            "example": "dep_735"
          },
          {
            "name": "counterparty_vendor_data",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `counterparty_vendor_data` promu.",
            "schema": {
              "type": "string"
            },
            "example": "user-77"
          },
          {
            "name": "matched_only",
            "in": "query",
            "required": false,
            "description": "`true` (également `1` ou `yes`, insensible à la casse) renvoie uniquement les événements pour lesquels au moins une règle a correspondu (`rules_matched_count` supérieur à 0). Toute autre valeur est ignorée.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": true
          },
          {
            "name": "occurred_from",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements dont `occurred_at` est supérieur ou égal à cet instant (inclus). Envoyez une valeur ISO 8601 : `2026-10-01T00:00:00Z`, un décalage explicite avec le `+` encodé en pourcentage (`2026-10-01T02:00:00%2B02:00` ; un `+` non encodé est décodé comme un espace et la valeur ne peut plus être analysée), ou une date seule (`2026-10-01`), ce qui correspond à 00:00:00 UTC de ce jour-là. Une valeur sans décalage est interprétée en UTC. Les valeurs dans tout autre format ne sont pas acceptées.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-10-01T00:00:00Z"
          },
          {
            "name": "occurred_to",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements dont `occurred_at` est inférieur ou égal à cet instant (inclus). Une date seule indique le début de cette journée, donc `occurred_to=2026-10-15` exclut le reste du 15 octobre ; envoyez `2026-10-15T23:59:59Z` pour l'inclure. Envoyez une valeur ISO 8601 : `2026-10-01T00:00:00Z`, un décalage explicite avec le `+` encodé en pourcentage (`2026-10-01T02:00:00%2B02:00` ; un `+` non encodé est décodé comme un espace et la valeur ne peut plus être analysée), ou une date seule (`2026-10-01`), ce qui correspond à 00:00:00 UTC de ce jour-là. Une valeur sans décalage est interprétée en UTC. Les valeurs dans tout autre format ne sont pas acceptées.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-10-17T23:59:59Z"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Correspondance insensible à la casse sur une sous-chaîne de `event_id`, `action_type`, `subject_vendor_data` ou `counterparty_vendor_data`.",
            "schema": {
              "type": "string"
            },
            "example": "chargeback"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/events/?event_category=payment&event_category=dispute&matched_only=true&occurred_from=2026-10-01T00:00:00Z&limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.monitoring_events.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.monitoringEvents.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.MonitoringEvents.ListAutoPaging(ctx, didit.MonitoringEventsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.monitoringEvents().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->monitoringEvents->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.monitoring_events.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.MonitoringEvents.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de résumés d'événements.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitoringEventPage"
                },
                "examples": {
                  "Payment and dispute events": {
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "event_uuid": "11111111-2222-3333-4444-555555555555",
                          "event_id": "chargeback-2026-10-16-000318",
                          "event_category": "dispute",
                          "action_type": "chargeback_opened",
                          "occurred_at": "2026-10-16T14:02:11Z",
                          "received_at": "2026-10-16T14:02:12.418230Z",
                          "status": "IN_REVIEW",
                          "score": 60,
                          "subject_vendor_data": "user-42",
                          "subject_entity_type": "individual",
                          "subject_uuid": "66666666-7777-8888-9999-000000000000",
                          "counterparty_vendor_data": null,
                          "session_id": null,
                          "device_fingerprint": null,
                          "ip_address": null,
                          "ip_country": null,
                          "amount": "250.000000000000000000",
                          "currency": "EUR",
                          "game_id": null,
                          "round_id": null,
                          "bonus_id": null,
                          "affiliate_code": null,
                          "payment_reference_id": "dep_735",
                          "retention_class": "monetary_or_compliance",
                          "rules_matched_count": 1,
                          "correlation_pending": false,
                          "is_droppable": false
                        },
                        {
                          "event_uuid": "22222222-3333-4444-5555-666666666666",
                          "event_id": "login-2026-10-15-000912",
                          "event_category": "auth",
                          "action_type": "login",
                          "occurred_at": "2026-10-15T08:30:00.120000Z",
                          "received_at": "2026-10-15T08:30:00.734512Z",
                          "status": "ACCEPTED",
                          "score": 0,
                          "subject_vendor_data": "user-42",
                          "subject_entity_type": "individual",
                          "subject_uuid": "66666666-7777-8888-9999-000000000000",
                          "counterparty_vendor_data": null,
                          "session_id": "web-session-abc",
                          "device_fingerprint": "fp-a8c1",
                          "ip_address": "203.0.113.42",
                          "ip_country": "ES",
                          "amount": null,
                          "currency": null,
                          "game_id": null,
                          "round_id": null,
                          "bonus_id": null,
                          "affiliate_code": null,
                          "payment_reference_id": null,
                          "retention_class": "standard",
                          "rules_matched_count": 0,
                          "correlation_pending": false,
                          "is_droppable": true
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`limit` ou `offset` est supérieur à 1000000. Le corps est un tableau JSON contenant un seul message. Un paramètre `limit` non numérique ou non positif utilise par défaut la valeur de 50 au lieu d'échouer.",
            "content": {
              "application/json": {
                "examples": {
                  "limit too large": {
                    "summary": "limite supérieure à 1000000",
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  },
                  "offset too large": {
                    "summary": "offset supérieur à 1000000",
                    "value": [
                      "offset must not exceed 1000000."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Seule une clé expirée renvoie `401` ; une clé manquante ou invalide renvoie `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Un en-tête `x-api-key` manquant (une clé erronée, révoquée ou expirée renvoie `401`), une clé restreinte sans `transactions: read`, une clé limitée à certains workflows ou à des sessions approuvées (une telle clé n'accède jamais aux données de surveillance des transactions), ou une requête provenant de l'extérieur de la liste d'autorisation IP de la clé.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without access": {
                    "value": {
                      "detail": "This API key has no read access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "IP not allowed": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les requêtes `GET` partagent un quota de 600 requêtes par minute par clé API. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer un événement de surveillance",
        "description": "Envoyez un événement non monétaire (connexion, session, jeu, bonus, affiliation, paiement, litige, sécurité, jeu responsable ou personnalisé) depuis votre backend. L'événement est validé par rapport au contrat de sa catégorie, stocké, enrichi par IP une fois par adresse publique unique, et évalué par vos règles d'événements en temps réel avant le renvoi de la réponse ; les règles multi-sujets et à fenêtre longue s'exécutent de manière asynchrone (`correlation_pending: true`), et dans une application sandbox, aucune règle ne s'exécute. `event_id` est la clé d'idempotence : le même `event_id` avec les mêmes `event_category`, `action_type`, `occurred_at`, `subject.vendor_data` et `payload` renvoie `200` avec `idempotent_replay: true` et le résultat stocké (les autres champs de l'enveloppe ne sont pas comparés), tandis que des valeurs différentes renvoient `409`. L'ingestion d'événements est activable par application : tant qu'elle n'est pas activée, cet endpoint renvoie `403` avec `code: event_monitoring_disabled` et n'enregistre rien. Une clé API restreinte nécessite `transactions: write`. Consultez [Ingestion d'événements](https://docs.didit.me/fr/transaction-monitoring/events) et [Règles sur les événements](https://docs.didit.me/fr/transaction-monitoring/event-rules) ; pour envoyer des événements depuis un navigateur ou une application, utilisez la [Soumission d'événements par SDK](https://docs.didit.me/fr/transaction-monitoring/sdk-event-submission).",
        "operationId": "create_monitoring_event",
        "x-didit-sdk": {
          "resource": "monitoring_events",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Monitoring Events"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MonitoringEventCreateRequest"
              },
              "examples": {
                "Login": {
                  "value": {
                    "event_id": "login-2026-10-17-000001",
                    "event_category": "auth",
                    "action_type": "login",
                    "occurred_at": "2026-10-17T09:15:02.481Z",
                    "time_zone": "Europe/Madrid",
                    "subject": {
                      "vendor_data": "user-42",
                      "entity_type": "individual"
                    },
                    "session": {
                      "session_id": "web-session-abc",
                      "sequence": 142
                    },
                    "device_context": {
                      "fingerprint": "fp-a8c1",
                      "network_context": {
                        "ip_address": "203.0.113.42"
                      }
                    },
                    "payload": {
                      "method": "password"
                    },
                    "custom_values": {
                      "vip_tier": "gold"
                    }
                  }
                },
                "Deposit completed": {
                  "value": {
                    "event_id": "deposit-2026-10-17-000002",
                    "event_category": "payment",
                    "action_type": "deposit_completed",
                    "occurred_at": "2026-10-17T09:16:40Z",
                    "subject": {
                      "vendor_data": "user-42"
                    },
                    "transaction_context": {
                      "amount": "100.00",
                      "currency": "EUR",
                      "direction": "inbound",
                      "payment_reference_id": "dep_736"
                    },
                    "payload": {
                      "payment_method": "card",
                      "status": "completed"
                    }
                  }
                },
                "Chargeback opened": {
                  "value": {
                    "event_id": "chargeback-2026-10-16-000318",
                    "event_category": "dispute",
                    "action_type": "chargeback_opened",
                    "occurred_at": "2026-10-16T14:02:11Z",
                    "subject": {
                      "vendor_data": "user-42"
                    },
                    "payload": {
                      "payment_reference_id": "dep_735",
                      "chargeback_id": "cb_5521",
                      "amount": "250.00",
                      "currency": "EUR",
                      "reason_code": "fraud"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/events/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"event_id\": \"login-2026-10-17-000001\",\n    \"event_category\": \"auth\",\n    \"action_type\": \"login\",\n    \"occurred_at\": \"2026-10-17T09:15:02.481Z\",\n    \"subject\": {\"vendor_data\": \"user-42\", \"entity_type\": \"individual\"},\n    \"session\": {\"session_id\": \"web-session-abc\", \"sequence\": 142},\n    \"device_context\": {\n      \"fingerprint\": \"fp-a8c1\",\n      \"network_context\": {\"ip_address\": \"203.0.113.42\"}\n    },\n    \"payload\": {\"method\": \"password\"}\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.monitoring_events.create(\n    event_id=\"login-2026-10-17-000001\",\n    event_category=\"auth\",\n    action_type=\"login\",\n    occurred_at=\"2026-10-17T09:15:02.481Z\",\n    time_zone=\"Europe/Madrid\",\n    subject={\n        \"vendor_data\": \"user-42\",\n        \"entity_type\": \"individual\",\n    },\n    session={\n        \"session_id\": \"web-session-abc\",\n        \"sequence\": 142,\n    },\n    device_context={\n        \"fingerprint\": \"fp-a8c1\",\n        \"network_context\": {\n            \"ip_address\": \"203.0.113.42\",\n        },\n    },\n    payload={\"method\": \"password\"},\n    custom_values={\"vip_tier\": \"gold\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.monitoringEvents.create({\n  event_id: \"login-2026-10-17-000001\",\n  event_category: \"auth\",\n  action_type: \"login\",\n  occurred_at: \"2026-10-17T09:15:02.481Z\",\n  time_zone: \"Europe/Madrid\",\n  subject: {\n    vendor_data: \"user-42\",\n    entity_type: \"individual\",\n  },\n  session: {\n    session_id: \"web-session-abc\",\n    sequence: 142,\n  },\n  device_context: {\n    fingerprint: \"fp-a8c1\",\n    network_context: {\n      ip_address: \"203.0.113.42\",\n    },\n  },\n  payload: { method: \"password\" },\n  custom_values: { vip_tier: \"gold\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.MonitoringEvents.Create(ctx, didit.MonitoringEventCreateRequest{\n\tEventID:       \"login-2026-10-17-000001\",\n\tEventCategory: \"auth\",\n\tActionType:    \"login\",\n\tOccurredAt:    time.Date(2026, 10, 17, 9, 15, 2, 0, time.UTC),\n\tTimeZone:      didit.String(\"Europe/Madrid\"),\n\tSubject: didit.MonitoringEventCreateRequestSubject{\n\t\tVendorData: \"user-42\",\n\t\tEntityType: didit.String(\"individual\"),\n\t},\n\tSession: didit.Some(didit.MonitoringEventCreateRequestSession{\n\t\tSessionID: didit.String(\"web-session-abc\"),\n\t\tSequence:  didit.Int(142),\n\t}),\n\tDeviceContext: didit.Some(didit.MonitoringEventCreateRequestDeviceContext{\n\t\tFingerprint: didit.String(\"fp-a8c1\"),\n\t\tNetworkContext: didit.Some(didit.MonitoringEventCreateRequestDeviceContextNetworkContext{\n\t\t\tIPAddress: didit.String(\"203.0.113.42\"),\n\t\t}),\n\t}),\n\tPayload:      didit.Some(map[string]any{\"method\": \"password\"}),\n\tCustomValues: didit.Some(map[string]any{\"vip_tier\": \"gold\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.OffsetDateTime;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.MonitoringEventCreateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.monitoringEvents().create(MonitoringEventCreateRequest.builder()\n        .eventId(\"login-2026-10-17-000001\")\n        .eventCategory(MonitoringEventCreateRequest.EventCategory.of(\"auth\"))\n        .actionType(\"login\")\n        .occurredAt(OffsetDateTime.parse(\"2026-10-17T09:15:02.481Z\"))\n        .timeZone(\"Europe/Madrid\")\n        .subject(MonitoringEventCreateRequest.Subject.builder()\n                .vendorData(\"user-42\")\n                .entityType(\"individual\")\n                .build())\n        .session(MonitoringEventCreateRequest.Session.builder()\n                .sessionId(\"web-session-abc\")\n                .sequence(142L)\n                .build())\n        .deviceContext(MonitoringEventCreateRequest.DeviceContext.builder()\n                .fingerprint(\"fp-a8c1\")\n                .networkContext(MonitoringEventCreateRequest.DeviceContext.NetworkContext.builder()\n                        .ipAddress(\"203.0.113.42\")\n                        .build())\n                .build())\n        .payload(Map.of(\"method\", \"password\"))\n        .customValues(Map.of(\"vip_tier\", MonitoringEventCreateRequest.CustomValuesValue.ofString(\"gold\")))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->monitoringEvents->create([\n    'event_id' => 'login-2026-10-17-000001',\n    'event_category' => 'auth',\n    'action_type' => 'login',\n    'occurred_at' => '2026-10-17T09:15:02.481Z',\n    'time_zone' => 'Europe/Madrid',\n    'subject' => [\n        'vendor_data' => 'user-42',\n        'entity_type' => 'individual',\n    ],\n    'session' => [\n        'session_id' => 'web-session-abc',\n        'sequence' => 142,\n    ],\n    'device_context' => [\n        'fingerprint' => 'fp-a8c1',\n        'network_context' => [\n            'ip_address' => '203.0.113.42',\n        ],\n    ],\n    'payload' => ['method' => 'password'],\n    'custom_values' => ['vip_tier' => 'gold'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.monitoring_events.create(\n  event_id: \"login-2026-10-17-000001\",\n  event_category: \"auth\",\n  action_type: \"login\",\n  occurred_at: \"2026-10-17T09:15:02.481Z\",\n  time_zone: \"Europe/Madrid\",\n  subject: {\n    vendor_data: \"user-42\",\n    entity_type: \"individual\",\n  },\n  session: {\n    session_id: \"web-session-abc\",\n    sequence: 142,\n  },\n  device_context: {\n    fingerprint: \"fp-a8c1\",\n    network_context: {\n      ip_address: \"203.0.113.42\",\n    },\n  },\n  payload: { method: \"password\" },\n  custom_values: { vip_tier: \"gold\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.MonitoringEvents.CreateAsync(new MonitoringEventCreateRequest\n{\n    EventId = \"login-2026-10-17-000001\",\n    EventCategory = \"auth\",\n    ActionType = \"login\",\n    OccurredAt = DateTimeOffset.Parse(\"2026-10-17T09:15:02.481Z\"),\n    TimeZone = \"Europe/Madrid\",\n    Subject = new()\n    {\n        VendorData = \"user-42\",\n        EntityType = \"individual\",\n    },\n    Session = new MonitoringEventCreateRequestSession\n    {\n        SessionId = \"web-session-abc\",\n        Sequence = 142,\n    },\n    DeviceContext = new MonitoringEventCreateRequestDeviceContext\n    {\n        Fingerprint = \"fp-a8c1\",\n        NetworkContext = new MonitoringEventCreateRequestDeviceContextNetworkContext\n        {\n            IpAddress = \"203.0.113.42\",\n        },\n    },\n    Payload = new Dictionary<string, object> { [\"method\"] = \"password\" },\n    CustomValues = new Dictionary<string, object> { [\"vip_tier\"] = \"gold\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "L'événement a été stocké et évalué.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitoringEventIngestResult"
                },
                "examples": {
                  "Stored, no rule matched": {
                    "value": {
                      "event_uuid": "33333333-4444-5555-6666-777777777777",
                      "event_id": "login-2026-10-17-000001",
                      "status": "ACCEPTED",
                      "score": 0,
                      "rules_evaluated_count": 6,
                      "rules_matched_count": 0,
                      "correlation_pending": false,
                      "retention_class": "standard",
                      "expires_at": "2026-11-16T09:15:02.481000Z",
                      "idempotent_replay": false,
                      "rule_matches": []
                    }
                  },
                  "Rule matched, async rule pending": {
                    "value": {
                      "event_uuid": "33333333-4444-5555-6666-777777777777",
                      "event_id": "login-2026-10-17-000001",
                      "status": "IN_REVIEW",
                      "score": 40,
                      "rules_evaluated_count": 6,
                      "rules_matched_count": 1,
                      "correlation_pending": true,
                      "retention_class": "risk_relevant",
                      "expires_at": "2027-01-15T09:15:02.481000Z",
                      "idempotent_replay": false,
                      "rule_matches": [
                        {
                          "rule_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                          "library_key": null,
                          "mode": "ACTIVE",
                          "is_async": false
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "200": {
            "description": "Rejeu idempotent : un événement avec cet `event_id` et le même contenu est déjà stocké. Rien n'a été stocké ni évalué à nouveau ; le corps décrit l'événement stocké.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitoringEventIngestResult"
                },
                "examples": {
                  "Replay": {
                    "value": {
                      "event_uuid": "33333333-4444-5555-6666-777777777777",
                      "event_id": "login-2026-10-17-000001",
                      "status": "ACCEPTED",
                      "score": 0,
                      "rules_evaluated_count": 6,
                      "rules_matched_count": 0,
                      "correlation_pending": false,
                      "retention_class": "standard",
                      "expires_at": "2026-11-16T09:15:02.481000Z",
                      "idempotent_replay": true,
                      "rule_matches": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Échec de la validation. Le corps est indexé par champ ; les champs imbriqués sont des objets imbriqués. Rien n'est enregistré.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing fields": {
                    "value": {
                      "event_id": [
                        "This field is required."
                      ],
                      "subject": [
                        "This field is required."
                      ]
                    }
                  },
                  "Unknown category": {
                    "value": {
                      "event_category": [
                        "\"login\" is not a valid choice."
                      ]
                    }
                  },
                  "occurred_at too old": {
                    "value": {
                      "occurred_at": [
                        "occurred_at is more than 7 days in the past. Use the batch import lane for backfills."
                      ]
                    }
                  },
                  "occurred_at in the future": {
                    "value": {
                      "occurred_at": [
                        "occurred_at is more than 5 minutes in the future."
                      ]
                    }
                  },
                  "Missing subject vendor_data": {
                    "value": {
                      "subject": {
                        "vendor_data": [
                          "This field is required."
                        ]
                      }
                    }
                  },
                  "Missing required payload keys": {
                    "value": {
                      "payload": [
                        "payment.deposit_completed requires: payment_method, status."
                      ]
                    }
                  },
                  "Missing one-of payload key": {
                    "value": {
                      "payload": [
                        "dispute.chargeback_opened requires one of: dispute_id, chargeback_id."
                      ]
                    }
                  },
                  "Security change without changed_field": {
                    "value": {
                      "payload": [
                        "security.*_changed requires 'changed_field'."
                      ]
                    }
                  },
                  "Payload too large": {
                    "value": {
                      "payload": [
                        "payload exceeds 16384 bytes. Summarise telemetry client-side."
                      ]
                    }
                  },
                  "Too many custom_values": {
                    "value": {
                      "custom_values": [
                        "custom_values accepts at most 100 keys."
                      ]
                    }
                  },
                  "Nested custom value": {
                    "value": {
                      "custom_values": [
                        "custom_values['limits'] must be a scalar - rule conditions cannot address nested values."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Seule une clé expirée renvoie `401` ; une clé manquante ou invalide renvoie `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Un en-tête `x-api-key` manquant (une clé erronée, révoquée ou expirée renvoie `401`), une clé restreinte sans `transactions: write`, une clé limitée à certains workflows ou à des sessions approuvées (une telle clé n'accède jamais aux données de surveillance des transactions), ou une requête provenant de l'extérieur de la liste d'autorisation IP de la clé. Également renvoyé avec `code: event_monitoring_disabled` lorsque l'ingestion d'événements est désactivée pour l'application ; rien n'est stocké dans ce cas, et la vérification s'exécute avant que le corps ne soit validé.",
            "content": {
              "application/json": {
                "examples": {
                  "Event monitoring disabled": {
                    "value": {
                      "detail": "Event monitoring is not enabled for this application. Turn on event ingestion in the transaction monitoring settings before submitting events.",
                      "code": "event_monitoring_disabled"
                    }
                  },
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without access": {
                    "value": {
                      "detail": "This API key has no write access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "IP not allowed": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`event_id` a déjà été utilisé pour un événement avec un contenu différent (catégorie, type d'action, `occurred_at`, `vendor_data` du sujet ou payload). Envoyez l'événement sous un nouvel `event_id`.",
            "content": {
              "application/json": {
                "examples": {
                  "event_id reused": {
                    "value": {
                      "event_id": "event_id 'login-2026-10-17-000001' already exists with a different payload."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les créations de transactions et l'ingestion d'événements (`POST /v3/transactions/`, `POST /v3/events/`, `POST /v3/events/batch/`) partagent un quota de 600 requêtes par minute par clé API, distinct des 300 requêtes partagées par toutes les autres requêtes d'écriture. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer, arrondies à l'unité supérieure pour que la tentative se fasse dans la fenêtre suivante.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Ingestion rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/events/batch/": {
      "post": {
        "summary": "Créer des événements de surveillance par lot",
        "description": "Soumettez 1 à 500 événements en une seule requête, chacun dans la même enveloppe que `POST /v3/events/`. Chaque élément est validé, stocké et évalué individuellement et reçoit son propre résultat (`accepted`, `replayed` ou `rejected`), de sorte qu'un événement malformé n'annule jamais les autres : la réponse est `201` lorsqu'aucun élément n'a été rejeté et `207` lorsqu'au moins un l'a été, les deux signifiant que la requête a été traitée. Envoyez `{\"events\": [...]}` ; un simple tableau JSON d'événements est également accepté. L'ingestion d'événements doit être activée pour l'application, sinon la requête entière renvoie `403` avec `code: event_monitoring_disabled` et rien n'est stocké. Une clé API avec restriction nécessite `transactions: write`. Voir [Lots](https://docs.didit.me/fr/transaction-monitoring/events#lots).",
        "operationId": "create_monitoring_events_batch",
        "x-didit-sdk": {
          "resource": "monitoring_events",
          "method": "create_batch",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Monitoring Events"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "events"
                ],
                "properties": {
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "description": "1 à 500 événements. Chaque élément suit `MonitoringEventCreateRequest`, y compris la fenêtre de 7 jours dans le passé et de 5 minutes dans le futur pour `occurred_at`.",
                    "items": {
                      "$ref": "#/components/schemas/MonitoringEventCreateRequest"
                    }
                  }
                }
              },
              "example": {
                "events": [
                  {
                    "event_id": "login-2026-10-17-000001",
                    "event_category": "auth",
                    "action_type": "login",
                    "occurred_at": "2026-10-17T09:15:02.481Z",
                    "subject": {
                      "vendor_data": "user-42"
                    }
                  },
                  {
                    "event_id": "deposit-2026-10-17-000002",
                    "event_category": "payment",
                    "action_type": "deposit_completed",
                    "occurred_at": "2026-10-17T09:16:40Z",
                    "subject": {
                      "vendor_data": "user-42"
                    },
                    "transaction_context": {
                      "amount": "100.00",
                      "currency": "EUR",
                      "payment_reference_id": "dep_736"
                    },
                    "payload": {
                      "payment_method": "card",
                      "status": "completed"
                    }
                  }
                ]
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/events/batch/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"events\": [\n      {\"event_id\": \"login-2026-10-17-000001\", \"event_category\": \"auth\", \"action_type\": \"login\",\n       \"occurred_at\": \"2026-10-17T09:15:02.481Z\", \"subject\": {\"vendor_data\": \"user-42\"}},\n      {\"event_id\": \"deposit-2026-10-17-000002\", \"event_category\": \"payment\", \"action_type\": \"deposit_completed\",\n       \"occurred_at\": \"2026-10-17T09:16:40.000Z\", \"subject\": {\"vendor_data\": \"user-42\"},\n       \"transaction_context\": {\"amount\": \"100.00\", \"currency\": \"EUR\", \"payment_reference_id\": \"dep_736\"},\n       \"payload\": {\"payment_method\": \"card\", \"status\": \"completed\"}}\n    ]\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.monitoring_events.create_batch(\n    events=[{\n        \"event_id\": \"login-2026-10-17-000001\",\n        \"event_category\": \"auth\",\n        \"action_type\": \"login\",\n        \"occurred_at\": \"2026-10-17T09:15:02.481Z\",\n        \"subject\": {\n            \"vendor_data\": \"user-42\",\n        },\n    }, {\n        \"event_id\": \"deposit-2026-10-17-000002\",\n        \"event_category\": \"payment\",\n        \"action_type\": \"deposit_completed\",\n        \"occurred_at\": \"2026-10-17T09:16:40Z\",\n        \"subject\": {\n            \"vendor_data\": \"user-42\",\n        },\n        \"transaction_context\": {\n            \"amount\": \"100.00\",\n            \"currency\": \"EUR\",\n            \"payment_reference_id\": \"dep_736\",\n        },\n        \"payload\": {\"payment_method\": \"card\", \"status\": \"completed\"},\n    }],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.monitoringEvents.createBatch({\n  events: [{\n    event_id: \"login-2026-10-17-000001\",\n    event_category: \"auth\",\n    action_type: \"login\",\n    occurred_at: \"2026-10-17T09:15:02.481Z\",\n    subject: {\n      vendor_data: \"user-42\",\n    },\n  }, {\n    event_id: \"deposit-2026-10-17-000002\",\n    event_category: \"payment\",\n    action_type: \"deposit_completed\",\n    occurred_at: \"2026-10-17T09:16:40Z\",\n    subject: {\n      vendor_data: \"user-42\",\n    },\n    transaction_context: {\n      amount: \"100.00\",\n      currency: \"EUR\",\n      payment_reference_id: \"dep_736\",\n    },\n    payload: { payment_method: \"card\", status: \"completed\" },\n  }],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.MonitoringEvents.CreateBatch(ctx, didit.MonitoringEventsCreateBatchParams{\n\tEvents: []didit.MonitoringEventCreateRequest{{\n\t\tEventID:       \"login-2026-10-17-000001\",\n\t\tEventCategory: \"auth\",\n\t\tActionType:    \"login\",\n\t\tOccurredAt:    time.Date(2026, 10, 17, 9, 15, 2, 0, time.UTC),\n\t\tSubject: didit.MonitoringEventCreateRequestSubject{\n\t\t\tVendorData: \"user-42\",\n\t\t},\n\t}, {\n\t\tEventID:       \"deposit-2026-10-17-000002\",\n\t\tEventCategory: \"payment\",\n\t\tActionType:    \"deposit_completed\",\n\t\tOccurredAt:    time.Date(2026, 10, 17, 9, 16, 40, 0, time.UTC),\n\t\tSubject: didit.MonitoringEventCreateRequestSubject{\n\t\t\tVendorData: \"user-42\",\n\t\t},\n\t\tTransactionContext: didit.Some(didit.MonitoringEventCreateRequestTransactionContext{\n\t\t\tAmount:             didit.String(\"100.00\"),\n\t\t\tCurrency:           didit.String(\"EUR\"),\n\t\t\tPaymentReferenceID: didit.String(\"dep_736\"),\n\t\t}),\n\t\tPayload: didit.Some(map[string]any{\"payment_method\": \"card\", \"status\": \"completed\"}),\n\t}},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.OffsetDateTime;\nimport java.util.List;\nimport java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.MonitoringEventCreateRequest;\nimport me.didit.types.MonitoringEventsCreateBatchParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.monitoringEvents().createBatch(MonitoringEventsCreateBatchParams.builder()\n        .events(List.of(\n                MonitoringEventCreateRequest.builder()\n                        .eventId(\"login-2026-10-17-000001\")\n                        .eventCategory(MonitoringEventCreateRequest.EventCategory.of(\"auth\"))\n                        .actionType(\"login\")\n                        .occurredAt(OffsetDateTime.parse(\"2026-10-17T09:15:02.481Z\"))\n                        .subject(MonitoringEventCreateRequest.Subject.builder()\n                                .vendorData(\"user-42\")\n                                .build())\n                        .build(),\n                MonitoringEventCreateRequest.builder()\n                        .eventId(\"deposit-2026-10-17-000002\")\n                        .eventCategory(MonitoringEventCreateRequest.EventCategory.of(\"payment\"))\n                        .actionType(\"deposit_completed\")\n                        .occurredAt(OffsetDateTime.parse(\"2026-10-17T09:16:40Z\"))\n                        .subject(MonitoringEventCreateRequest.Subject.builder()\n                                .vendorData(\"user-42\")\n                                .build())\n                        .transactionContext(MonitoringEventCreateRequest.TransactionContext.builder()\n                                .amount(\"100.00\")\n                                .currency(\"EUR\")\n                                .paymentReferenceId(\"dep_736\")\n                                .build())\n                        .payload(Map.of(\"payment_method\", \"card\", \"status\", \"completed\"))\n                        .build()))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->monitoringEvents->createBatch([\n    'events' => [[\n        'event_id' => 'login-2026-10-17-000001',\n        'event_category' => 'auth',\n        'action_type' => 'login',\n        'occurred_at' => '2026-10-17T09:15:02.481Z',\n        'subject' => [\n            'vendor_data' => 'user-42',\n        ],\n    ], [\n        'event_id' => 'deposit-2026-10-17-000002',\n        'event_category' => 'payment',\n        'action_type' => 'deposit_completed',\n        'occurred_at' => '2026-10-17T09:16:40Z',\n        'subject' => [\n            'vendor_data' => 'user-42',\n        ],\n        'transaction_context' => [\n            'amount' => '100.00',\n            'currency' => 'EUR',\n            'payment_reference_id' => 'dep_736',\n        ],\n        'payload' => ['payment_method' => 'card', 'status' => 'completed'],\n    ]],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.monitoring_events.create_batch(\n  events: [{\n    event_id: \"login-2026-10-17-000001\",\n    event_category: \"auth\",\n    action_type: \"login\",\n    occurred_at: \"2026-10-17T09:15:02.481Z\",\n    subject: {\n      vendor_data: \"user-42\",\n    },\n  }, {\n    event_id: \"deposit-2026-10-17-000002\",\n    event_category: \"payment\",\n    action_type: \"deposit_completed\",\n    occurred_at: \"2026-10-17T09:16:40Z\",\n    subject: {\n      vendor_data: \"user-42\",\n    },\n    transaction_context: {\n      amount: \"100.00\",\n      currency: \"EUR\",\n      payment_reference_id: \"dep_736\",\n    },\n    payload: { payment_method: \"card\", status: \"completed\" },\n  }]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.MonitoringEvents.CreateBatchAsync(new MonitoringEventsCreateBatchParams\n{\n    Events = new MonitoringEventCreateRequest[]\n    {\n        new()\n        {\n            EventId = \"login-2026-10-17-000001\",\n            EventCategory = \"auth\",\n            ActionType = \"login\",\n            OccurredAt = DateTimeOffset.Parse(\"2026-10-17T09:15:02.481Z\"),\n            Subject = new()\n            {\n                VendorData = \"user-42\",\n            },\n        },\n        new()\n        {\n            EventId = \"deposit-2026-10-17-000002\",\n            EventCategory = \"payment\",\n            ActionType = \"deposit_completed\",\n            OccurredAt = DateTimeOffset.Parse(\"2026-10-17T09:16:40Z\"),\n            Subject = new()\n            {\n                VendorData = \"user-42\",\n            },\n            TransactionContext = new MonitoringEventCreateRequestTransactionContext\n            {\n                Amount = \"100.00\",\n                Currency = \"EUR\",\n                PaymentReferenceId = \"dep_736\",\n            },\n            Payload = new Dictionary<string, object> { [\"payment_method\"] = \"card\", [\"status\"] = \"completed\" },\n        },\n    },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Aucun élément n'a été rejeté : chaque élément est `accepted` ou `replayed`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "accepted_count",
                    "replayed_count",
                    "rejected_count",
                    "results"
                  ],
                  "properties": {
                    "accepted_count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Éléments stockés et évalués."
                    },
                    "replayed_count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Éléments déjà stockés avec le même contenu."
                    },
                    "rejected_count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Éléments non stockés."
                    },
                    "results": {
                      "type": "array",
                      "description": "Une entrée par élément, dans l'ordre de la requête.",
                      "items": {
                        "type": "object",
                        "description": "Résultat d'un élément. Les éléments acceptés et rejoués comportent également chaque champ de `MonitoringEventIngestResult` ; les éléments rejetés comportent `event_id` et `errors` à la place.",
                        "required": [
                          "index",
                          "outcome"
                        ],
                        "properties": {
                          "index": {
                            "type": "integer",
                            "minimum": 0,
                            "description": "Position de l'élément dans votre tableau `events`."
                          },
                          "outcome": {
                            "type": "string",
                            "enum": [
                              "accepted",
                              "replayed",
                              "rejected"
                            ],
                            "description": "`accepted` : stocké et évalué. `replayed` : déjà stocké avec le même contenu. `rejected` : non stocké ; voir `errors`."
                          },
                          "event_id": {
                            "type": "string",
                            "nullable": true,
                            "description": "Votre `event_id`. Sur les éléments rejetés par la validation, il est lu à partir de la clé snake_case `event_id` de l'élément ; il est donc nul lorsque l'élément l'a omis ou a envoyé l'alias `eventId`."
                          },
                          "errors": {
                            "type": "object",
                            "additionalProperties": true,
                            "description": "Éléments rejetés uniquement. Erreurs de validation indexées par champ, sous le même format que le `400` de `POST /v3/events/` ; un `event_id` réutilisé avec un contenu différent est signalé sous forme de chaîne sous `errors.event_id`."
                          },
                          "event_uuid": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "ACCEPTED",
                              "APPROVED",
                              "IN_REVIEW",
                              "DECLINED"
                            ],
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "score": {
                            "type": "integer",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "rules_evaluated_count": {
                            "type": "integer",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "rules_matched_count": {
                            "type": "integer",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "correlation_pending": {
                            "type": "boolean",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "retention_class": {
                            "type": "string",
                            "enum": [
                              "low_value",
                              "standard",
                              "risk_relevant",
                              "monetary_or_compliance"
                            ],
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "expires_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "idempotent_replay": {
                            "type": "boolean",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "rule_matches": {
                            "type": "array",
                            "description": "Éléments acceptés et rejoués uniquement.",
                            "items": {
                              "type": "object",
                              "required": [
                                "rule_id",
                                "library_key",
                                "mode",
                                "is_async"
                              ],
                              "properties": {
                                "rule_id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "description": "UUID de la règle."
                                },
                                "library_key": {
                                  "type": "string",
                                  "nullable": true,
                                  "description": "Clé de bibliothèque lorsque la règle a été installée depuis la bibliothèque de règles, sinon null."
                                },
                                "mode": {
                                  "type": "string",
                                  "enum": [
                                    "ACTIVE",
                                    "TEST"
                                  ],
                                  "description": "Les règles `TEST` enregistrent la correspondance mais n'appliquent aucune action."
                                },
                                "is_async": {
                                  "type": "boolean",
                                  "description": "`true` lorsque la correspondance provient de la passe asynchrone."
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "All landed": {
                    "value": {
                      "accepted_count": 1,
                      "replayed_count": 1,
                      "rejected_count": 0,
                      "results": [
                        {
                          "index": 0,
                          "outcome": "accepted",
                          "event_uuid": "33333333-4444-5555-6666-777777777777",
                          "event_id": "login-2026-10-17-000001",
                          "status": "ACCEPTED",
                          "score": 0,
                          "rules_evaluated_count": 6,
                          "rules_matched_count": 0,
                          "correlation_pending": false,
                          "retention_class": "standard",
                          "expires_at": "2026-11-16T09:15:02.481000Z",
                          "idempotent_replay": false,
                          "rule_matches": []
                        },
                        {
                          "index": 1,
                          "outcome": "replayed",
                          "event_uuid": "11111111-2222-3333-4444-555555555555",
                          "event_id": "deposit-2026-10-17-000002",
                          "status": "ACCEPTED",
                          "score": 0,
                          "rules_evaluated_count": 6,
                          "rules_matched_count": 0,
                          "correlation_pending": false,
                          "retention_class": "monetary_or_compliance",
                          "expires_at": null,
                          "idempotent_replay": true,
                          "rule_matches": []
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "207": {
            "description": "Au moins un élément a été rejeté. Les autres éléments ont été stockés ; corrigez et renvoyez uniquement les éléments rejetés (le renvoi d'un élément accepté est sans risque, il revient avec le statut `replayed`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "accepted_count",
                    "replayed_count",
                    "rejected_count",
                    "results"
                  ],
                  "properties": {
                    "accepted_count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Éléments stockés et évalués."
                    },
                    "replayed_count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Éléments déjà stockés avec le même contenu."
                    },
                    "rejected_count": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Éléments non stockés."
                    },
                    "results": {
                      "type": "array",
                      "description": "Une entrée par élément, dans l'ordre de la requête.",
                      "items": {
                        "type": "object",
                        "description": "Résultat d'un élément. Les éléments acceptés et rejoués comportent également chaque champ de `MonitoringEventIngestResult` ; les éléments rejetés comportent `event_id` et `errors` à la place.",
                        "required": [
                          "index",
                          "outcome"
                        ],
                        "properties": {
                          "index": {
                            "type": "integer",
                            "minimum": 0,
                            "description": "Position de l'élément dans votre tableau `events`."
                          },
                          "outcome": {
                            "type": "string",
                            "enum": [
                              "accepted",
                              "replayed",
                              "rejected"
                            ],
                            "description": "`accepted` : stocké et évalué. `replayed` : déjà stocké avec le même contenu. `rejected` : non stocké ; voir `errors`."
                          },
                          "event_id": {
                            "type": "string",
                            "nullable": true,
                            "description": "Votre `event_id`. Sur les éléments rejetés par la validation, il est lu à partir de la clé snake_case `event_id` de l'élément ; il est donc nul lorsque l'élément l'a omis ou a envoyé l'alias `eventId`."
                          },
                          "errors": {
                            "type": "object",
                            "additionalProperties": true,
                            "description": "Éléments rejetés uniquement. Erreurs de validation indexées par champ, sous le même format que le `400` de `POST /v3/events/` ; un `event_id` réutilisé avec un contenu différent est signalé sous forme de chaîne sous `errors.event_id`."
                          },
                          "event_uuid": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "ACCEPTED",
                              "APPROVED",
                              "IN_REVIEW",
                              "DECLINED"
                            ],
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "score": {
                            "type": "integer",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "rules_evaluated_count": {
                            "type": "integer",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "rules_matched_count": {
                            "type": "integer",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "correlation_pending": {
                            "type": "boolean",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "retention_class": {
                            "type": "string",
                            "enum": [
                              "low_value",
                              "standard",
                              "risk_relevant",
                              "monetary_or_compliance"
                            ],
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "expires_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "idempotent_replay": {
                            "type": "boolean",
                            "description": "Éléments acceptés et rejoués uniquement."
                          },
                          "rule_matches": {
                            "type": "array",
                            "description": "Éléments acceptés et rejoués uniquement.",
                            "items": {
                              "type": "object",
                              "required": [
                                "rule_id",
                                "library_key",
                                "mode",
                                "is_async"
                              ],
                              "properties": {
                                "rule_id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "description": "UUID de la règle."
                                },
                                "library_key": {
                                  "type": "string",
                                  "nullable": true,
                                  "description": "Clé de bibliothèque lorsque la règle a été installée depuis la bibliothèque de règles, sinon null."
                                },
                                "mode": {
                                  "type": "string",
                                  "enum": [
                                    "ACTIVE",
                                    "TEST"
                                  ],
                                  "description": "Les règles `TEST` enregistrent la correspondance mais n'appliquent aucune action."
                                },
                                "is_async": {
                                  "type": "boolean",
                                  "description": "`true` lorsque la correspondance provient de la passe asynchrone."
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Partial success": {
                    "value": {
                      "accepted_count": 1,
                      "replayed_count": 0,
                      "rejected_count": 2,
                      "results": [
                        {
                          "index": 0,
                          "outcome": "accepted",
                          "event_uuid": "33333333-4444-5555-6666-777777777777",
                          "event_id": "login-2026-10-17-000001",
                          "status": "ACCEPTED",
                          "score": 0,
                          "rules_evaluated_count": 6,
                          "rules_matched_count": 0,
                          "correlation_pending": false,
                          "retention_class": "standard",
                          "expires_at": "2026-11-16T09:15:02.481000Z",
                          "idempotent_replay": false,
                          "rule_matches": []
                        },
                        {
                          "index": 1,
                          "event_id": "deposit-2026-10-17-000002",
                          "outcome": "rejected",
                          "errors": {
                            "payload": [
                              "payment.deposit_completed requires: payment_method, status."
                            ]
                          }
                        },
                        {
                          "index": 2,
                          "event_id": "login-2026-10-16-000777",
                          "outcome": "rejected",
                          "errors": {
                            "event_id": "event_id 'login-2026-10-16-000777' already exists with a different payload."
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le lot lui-même est malformé : `events` est manquant ou n'est pas un tableau, est vide ou comporte plus de 500 éléments. Rien n'est enregistré ; fractionnez les lots volumineux.",
            "content": {
              "application/json": {
                "examples": {
                  "Not a list": {
                    "value": {
                      "events": "Expected a list of events."
                    }
                  },
                  "Empty": {
                    "value": {
                      "events": "At least one event is required."
                    }
                  },
                  "Too many": {
                    "value": {
                      "events": "A batch accepts at most 500 events; received 612."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Seule une clé expirée renvoie `401` ; une clé manquante ou invalide renvoie `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Un en-tête `x-api-key` manquant (une clé erronée, révoquée ou expirée renvoie `401`), une clé restreinte sans `transactions: write`, une clé limitée à certains workflows ou à des sessions approuvées (une telle clé n'accède jamais aux données de surveillance des transactions), ou une requête provenant de l'extérieur de la liste d'autorisation IP de la clé. Également renvoyé avec `code: event_monitoring_disabled` lorsque l'ingestion d'événements est désactivée pour l'application ; rien n'est stocké dans ce cas, et la vérification s'exécute avant que le corps ne soit validé.",
            "content": {
              "application/json": {
                "examples": {
                  "Event monitoring disabled": {
                    "value": {
                      "detail": "Event monitoring is not enabled for this application. Turn on event ingestion in the transaction monitoring settings before submitting events.",
                      "code": "event_monitoring_disabled"
                    }
                  },
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without access": {
                    "value": {
                      "detail": "This API key has no write access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "IP not allowed": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les créations de transactions et l'ingestion d'événements (`POST /v3/transactions/`, `POST /v3/events/`, `POST /v3/events/batch/`) partagent un quota de 600 requêtes par minute par clé API, distinct des 300 requêtes partagées par toutes les autres requêtes d'écriture. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer, arrondies à l'unité supérieure pour que la tentative se fasse dans la fenêtre suivante.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Ingestion rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/events/sdk-token/": {
      "post": {
        "summary": "Émettre un token SDK de surveillance",
        "description": "Émettez un identifiant d'appareil à courte durée de vie lié à un sujet, afin que votre application web ou mobile puisse envoyer les événements de cet utilisateur directement à Didit sans clé API. L'application transmet le `monitoring_token` retourné dans l'en-tête `X-Monitoring-Token` au canal d'appareil (`POST /v1/events/` et `POST /v1/events/batch/`), où le sujet est toujours écrasé par ce `vendor_data`, les événements en dehors de `allowed_event_categories` sont rejetés, chaque événement envoyé consomme une utilisation, et une requête dont l'`Origin` n'est pas égal à `bind_to_origin` est refusée. Appelez-le uniquement depuis votre backend ; l'émission crée l'identifiant et rien d'autre (aucun utilisateur n'est créé). L'ingestion d'événements doit être activée pour l'application, sinon cet endpoint renvoie `403` avec `code: event_monitoring_disabled` au lieu d'émettre un identifiant qui ne pourrait jamais écrire. Une clé API avec restriction de portée nécessite `transactions: write`. Voir [Soumission d'événements par le SDK](https://docs.didit.me/fr/transaction-monitoring/sdk-event-submission).",
        "operationId": "create_monitoring_event_sdk_token",
        "x-didit-sdk": {
          "resource": "monitoring_events",
          "method": "create_sdk_token",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Monitoring Events"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Les alias en camelCase sont acceptés : `vendorData`, `entityType`, `allowedEventCategories`, `ttlSeconds`, `maxUses`, `bindToOrigin`.",
                "required": [
                  "vendor_data"
                ],
                "properties": {
                  "vendor_data": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "Votre identifiant pour le sujet auquel appartient chaque événement soumis avec cet identifiant d'accès."
                  },
                  "entity_type": {
                    "type": "string",
                    "maxLength": 32,
                    "default": "individual",
                    "description": "`company` associe un sujet de type entreprise ; toute autre valeur (`individual` par défaut) associe un individu."
                  },
                  "allowed_event_categories": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "auth",
                        "session",
                        "gameplay",
                        "bonus",
                        "affiliate",
                        "payment",
                        "dispute",
                        "security",
                        "responsible_gambling",
                        "custom"
                      ]
                    },
                    "description": "Catégories que l'identifiant peut soumettre. Omettez-le ou envoyez `[]` pour autoriser toutes les catégories."
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 86400,
                    "default": 900,
                    "description": "Durée de vie des informations d'identification en secondes."
                  },
                  "max_uses": {
                    "type": "integer",
                    "minimum": 1,
                    "nullable": true,
                    "default": 1000,
                    "description": "Nombre d'événements que l'identifiant peut soumettre (un lot consomme une utilisation par événement). Envoyez `null` pour ne pas appliquer de plafond pendant la durée de validité."
                  },
                  "bind_to_origin": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true,
                    "description": "Lorsqu'il est défini, l'en-tête `Origin` du navigateur de chaque requête de l'appareil doit correspondre exactement à cette valeur ; une requête sans `Origin` est refusée."
                  }
                }
              },
              "example": {
                "vendor_data": "user-42",
                "allowed_event_categories": [
                  "auth",
                  "session",
                  "gameplay"
                ],
                "ttl_seconds": 900,
                "max_uses": 1000,
                "bind_to_origin": "https://app.example.com"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/events/sdk-token/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"vendor_data\": \"user-42\",\n    \"allowed_event_categories\": [\"auth\", \"session\", \"gameplay\"],\n    \"ttl_seconds\": 900,\n    \"max_uses\": 1000,\n    \"bind_to_origin\": \"https://app.example.com\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.monitoring_events.create_sdk_token(\n    vendor_data=\"user-42\",\n    allowed_event_categories=[\"auth\", \"session\", \"gameplay\"],\n    ttl_seconds=900,\n    max_uses=1000,\n    bind_to_origin=\"https://app.example.com\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.monitoringEvents.createSdkToken({\n  vendor_data: \"user-42\",\n  allowed_event_categories: [\"auth\", \"session\", \"gameplay\"],\n  ttl_seconds: 900,\n  max_uses: 1000,\n  bind_to_origin: \"https://app.example.com\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.MonitoringEvents.CreateSDKToken(ctx, didit.MonitoringEventsCreateSDKTokenParams{\n\tVendorData:             \"user-42\",\n\tAllowedEventCategories: didit.Some([]didit.MonitoringEventsCreateSDKTokenParamsAllowedEventCategories{\"auth\", \"session\", \"gameplay\"}),\n\tTTLSeconds:             didit.Int(900),\n\tMaxUses:                didit.Int(1000),\n\tBindToOrigin:           didit.String(\"https://app.example.com\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.MonitoringEventsCreateSdkTokenParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.monitoringEvents().createSdkToken(MonitoringEventsCreateSdkTokenParams.builder()\n        .vendorData(\"user-42\")\n        .allowedEventCategories(List.of(MonitoringEventsCreateSdkTokenParams.AllowedEventCategories.of(\"auth\"), MonitoringEventsCreateSdkTokenParams.AllowedEventCategories.of(\"session\"), MonitoringEventsCreateSdkTokenParams.AllowedEventCategories.of(\"gameplay\")))\n        .ttlSeconds(900L)\n        .maxUses(1000L)\n        .bindToOrigin(\"https://app.example.com\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->monitoringEvents->createSdkToken([\n    'vendor_data' => 'user-42',\n    'allowed_event_categories' => ['auth', 'session', 'gameplay'],\n    'ttl_seconds' => 900,\n    'max_uses' => 1000,\n    'bind_to_origin' => 'https://app.example.com',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.monitoring_events.create_sdk_token(\n  vendor_data: \"user-42\",\n  allowed_event_categories: [\"auth\", \"session\", \"gameplay\"],\n  ttl_seconds: 900,\n  max_uses: 1000,\n  bind_to_origin: \"https://app.example.com\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.MonitoringEvents.CreateSdkTokenAsync(new MonitoringEventsCreateSdkTokenParams\n{\n    VendorData = \"user-42\",\n    AllowedEventCategories = new MonitoringEventsCreateSdkTokenParamsAllowedEventCategories[] { \"auth\", \"session\", \"gameplay\" },\n    TtlSeconds = 900,\n    MaxUses = 1000,\n    BindToOrigin = \"https://app.example.com\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "L'identifiant d'authentification a été créé. Transmettez `monitoring_token` à l'application et traitez-le comme un secret jusqu'à `expires_at`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "monitoring_token",
                    "expires_at",
                    "allowed_event_categories",
                    "max_uses",
                    "bind_to_origin"
                  ],
                  "properties": {
                    "monitoring_token": {
                      "type": "string",
                      "description": "L'identifiant d'authentification de l'appareil (un token de 43 caractères compatible avec les URL). Envoyez-le dans l'en-tête `X-Monitoring-Token`."
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Date et heure à partir desquelles le justificatif cesse d'être accepté."
                    },
                    "allowed_event_categories": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "auth",
                          "session",
                          "gameplay",
                          "bonus",
                          "affiliate",
                          "payment",
                          "dispute",
                          "security",
                          "responsible_gambling",
                          "custom"
                        ]
                      },
                      "description": "Catégories que l'identifiant peut soumettre ; `[]` signifie toutes les catégories."
                    },
                    "max_uses": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Budget d'événements de l'identifiant ; null signifie sans plafond."
                    },
                    "bind_to_origin": {
                      "type": "string",
                      "nullable": true,
                      "description": "Origine à laquelle l'élément d'authentification est lié, ou null."
                    }
                  }
                },
                "example": {
                  "monitoring_token": "q7ZtR2xKp9VbN4mWc8LdH1sYfJ3gT6uEaQ0oPiXzBkC",
                  "expires_at": "2026-10-17T09:30:02.481000Z",
                  "allowed_event_categories": [
                    "auth",
                    "session",
                    "gameplay"
                  ],
                  "max_uses": 1000,
                  "bind_to_origin": "https://app.example.com"
                }
              }
            }
          },
          "400": {
            "description": "Échec de la validation : `vendor_data` manquant, `ttl_seconds` en dehors de 60 à 86400, `max_uses` inférieur à 1 ou une catégorie inconnue (indexée par sa position dans le tableau).",
            "content": {
              "application/json": {
                "examples": {
                  "Missing vendor_data": {
                    "value": {
                      "vendor_data": [
                        "This field is required."
                      ]
                    }
                  },
                  "ttl_seconds too short": {
                    "value": {
                      "ttl_seconds": [
                        "Ensure this value is greater than or equal to 60."
                      ]
                    }
                  },
                  "Unknown category": {
                    "value": {
                      "allowed_event_categories": {
                        "1": [
                          "\"login\" is not a valid choice."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Seule une clé expirée renvoie `401` ; une clé manquante ou invalide renvoie `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Un en-tête `x-api-key` manquant (une clé erronée, révoquée ou expirée renvoie `401`), une clé restreinte sans `transactions: write`, une clé limitée à certains workflows ou à des sessions approuvées (une telle clé n'accède jamais aux données de surveillance des transactions), ou une requête provenant de l'extérieur de la liste d'autorisation IP de la clé. Également renvoyé avec `code: event_monitoring_disabled` lorsque l'ingestion d'événements est désactivée pour l'application ; rien n'est stocké dans ce cas, et la vérification s'exécute avant que le corps ne soit validé.",
            "content": {
              "application/json": {
                "examples": {
                  "Event monitoring disabled": {
                    "value": {
                      "detail": "Event monitoring is not enabled for this application. Turn on event ingestion in the transaction monitoring settings before submitting events.",
                      "code": "event_monitoring_disabled"
                    }
                  },
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without access": {
                    "value": {
                      "detail": "This API key has no write access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "IP not allowed": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les requêtes d'écriture (`POST`, `PATCH`, `DELETE`) partagent un quota de 300 requêtes par minute par clé API. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/events/{event_uuid}/": {
      "get": {
        "summary": "Obtenir l'événement de surveillance",
        "description": "Récupérer un événement de surveillance avec tout ce que la liste renvoie, plus le payload, les valeurs personnalisées, le contexte de l'appareil, la provenance des champs (`field_sources`), les champs de domaine promus, `expires_at`, chaque exécution de règle correspondante avec ses preuves, l'enrichissement IP et les tags associés aux règles. Tant que `correlation_pending` est à `true`, une règle asynchrone doit encore s'exécuter ; relisez l'événement quelques minutes plus tard pour obtenir les valeurs finales de `status`, `score` et `rule_runs`. Les lectures fonctionnent que l'ingestion d'événements soit activée ou non. Une clé API avec restriction de portée nécessite `transactions: read`. Voir [Preuves](https://docs.didit.me/fr/transaction-monitoring/event-rules#preuves) et [Enrichissement IP](https://docs.didit.me/fr/transaction-monitoring/ip-enrichment).",
        "operationId": "get_monitoring_event",
        "x-didit-sdk": {
          "resource": "monitoring_events",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Monitoring Events"
        ],
        "parameters": [
          {
            "name": "event_uuid",
            "in": "path",
            "required": true,
            "description": "Identifiant Didit de l'événement (`event_uuid` issu de la réponse de création, de lot, de liste ou de chronologie), et non votre propre `event_id`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/events/11111111-2222-3333-4444-555555555555/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.monitoring_events.retrieve(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.monitoringEvents.retrieve(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.MonitoringEvents.Retrieve(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.monitoringEvents().retrieve(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->monitoringEvents->retrieve('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.monitoring_events.retrieve(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.MonitoringEvents.RetrieveAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'événement avec ses éléments de preuve.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitoringEventDetail"
                },
                "examples": {
                  "Login from a VPN, in review": {
                    "value": {
                      "event_uuid": "33333333-4444-5555-6666-777777777777",
                      "event_id": "login-2026-10-17-000001",
                      "event_category": "auth",
                      "action_type": "login",
                      "occurred_at": "2026-10-17T09:15:02.481000Z",
                      "received_at": "2026-10-17T09:15:02.903114Z",
                      "status": "IN_REVIEW",
                      "score": 40,
                      "subject_vendor_data": "user-42",
                      "subject_entity_type": "individual",
                      "subject_uuid": "66666666-7777-8888-9999-000000000000",
                      "counterparty_vendor_data": null,
                      "session_id": "web-session-abc",
                      "device_fingerprint": "fp-a8c1",
                      "ip_address": "203.0.113.42",
                      "ip_country": "ES",
                      "amount": null,
                      "currency": null,
                      "game_id": null,
                      "round_id": null,
                      "bonus_id": null,
                      "affiliate_code": null,
                      "payment_reference_id": null,
                      "retention_class": "risk_relevant",
                      "rules_matched_count": 1,
                      "correlation_pending": false,
                      "is_droppable": true,
                      "payload": {
                        "method": "password"
                      },
                      "custom_values": {
                        "vip_tier": "gold",
                        "vpn_or_proxy_detected": true
                      },
                      "device_context": {
                        "fingerprint": "fp-a8c1",
                        "network_context": {
                          "ip_address": "203.0.113.42",
                          "ip_country": "Spain",
                          "ip_country_code": "ES",
                          "ip_city": "Madrid",
                          "asn_number": 64500,
                          "asn_organization": "Example Networks",
                          "is_vpn_or_tor": true,
                          "is_data_center": false
                        }
                      },
                      "field_sources": {
                        "subject.vendor_data": "customer",
                        "event_category": "customer",
                        "action_type": "customer",
                        "occurred_at": "customer",
                        "received_at": "server",
                        "payload.method": "customer",
                        "session.session_id": "customer",
                        "session.sequence": "customer",
                        "device_context.fingerprint": "customer",
                        "device_context.network_context.ip_address": "customer",
                        "device_context.network_context.ip_country": "server",
                        "device_context.network_context.ip_country_code": "server",
                        "device_context.network_context.ip_city": "server",
                        "device_context.network_context.asn_number": "server",
                        "device_context.network_context.asn_organization": "server",
                        "device_context.network_context.is_vpn_or_tor": "server",
                        "device_context.network_context.is_data_center": "server"
                      },
                      "session_sequence": 142,
                      "table_id": null,
                      "hand_id": null,
                      "match_id": null,
                      "market_id": null,
                      "side": null,
                      "role": null,
                      "net_result_amount": null,
                      "payment_fingerprint": null,
                      "instrument_reference_hash": null,
                      "withdrawal_address_hash": null,
                      "dispute_id": null,
                      "chargeback_id": null,
                      "changed_field": null,
                      "identity_match_ref": null,
                      "schema_version": 1,
                      "expires_at": "2027-01-15T09:15:02.481000Z",
                      "rules_evaluated_count": 6,
                      "rule_runs": [
                        {
                          "rule_uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                          "rule_title": "Login from VPN or Tor",
                          "library_key": null,
                          "matched": true,
                          "mode": "ACTIVE",
                          "is_async": false,
                          "severity": "MEDIUM",
                          "score_delta": 40,
                          "action_summary": "score +40; add_tag:VPN_LOGIN",
                          "matched_payload": [
                            {
                              "field": "event.ip.is_vpn_or_tor",
                              "operator": "eq",
                              "expected_value": true,
                              "current_value": true,
                              "matched": true,
                              "group_index": null,
                              "group_logic": "AND",
                              "field_source": "server"
                            }
                          ],
                          "created_at": "2026-10-17T09:15:02.951207Z"
                        }
                      ],
                      "ip_enrichment": {
                        "ip_country_code": "ES",
                        "ip_city": "Madrid",
                        "asn_number": 64500,
                        "asn_organization": "Example Networks",
                        "is_vpn_or_tor": true,
                        "is_data_center": false,
                        "proxy_type": null,
                        "last_enriched_at": "2026-10-17T09:15:02.910442Z"
                      },
                      "subject_profile": null,
                      "tags": [
                        "VPN_LOGIN"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Seule une clé expirée renvoie `401` ; une clé manquante ou invalide renvoie `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Un en-tête `x-api-key` manquant (une clé erronée, révoquée ou expirée renvoie `401`), une clé restreinte sans `transactions: read`, une clé limitée à certains workflows ou à des sessions approuvées (une telle clé n'accède jamais aux données de surveillance des transactions), ou une requête provenant de l'extérieur de la liste d'autorisation IP de la clé.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without access": {
                    "value": {
                      "detail": "This API key has no read access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "IP not allowed": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun événement avec cet `event_uuid` n'existe dans l'application : il n'a jamais été enregistré, il a été supprimé ou il appartient à une autre application. Un segment de chemin qui n'est pas un UUID ne correspond pas à la route et renvoie également `404`.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No MonitoringEvent matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les requêtes `GET` partagent un quota de 600 requêtes par minute par clé API. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/events/subjects/{vendor_data}/": {
      "get": {
        "summary": "Obtenir la chronologie des événements du sujet",
        "description": "Lister tous les événements de surveillance d'un sujet, du plus récent au plus ancien selon `occurred_at`. Un identifiant `vendor_data` n'est unique qu'au sein d'un même type d'entité, de sorte qu'un même identifiant peut désigner à la fois une personne physique et une entreprise : `entity_type` détermine la chronologie obtenue, avec `individual` par défaut, les événements d'une entreprise nécessitent donc `entity_type=company`. Les filtres de `GET /v3/events/` s'appliquent en plus, et un `vendor_data` sans aucun événement renvoie une page vide plutôt qu'une erreur `404`. Une clé API restreinte nécessite `transactions: read`. Voir [Lecture des événements](https://docs.didit.me/fr/transaction-monitoring/events#relire-les-événements).",
        "operationId": "get_monitoring_event_subject_timeline",
        "x-didit-sdk": {
          "resource": "monitoring_events",
          "method": "retrieve_subject_timeline",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Monitoring Events"
        ],
        "parameters": [
          {
            "name": "vendor_data",
            "in": "path",
            "required": true,
            "description": "Votre identifiant pour le sujet (`subject.vendor_data` de ses événements). Encodez-le au format URL ; une valeur contenant `/` ne peut pas être adressée par cet endpoint.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            },
            "example": "user-42"
          },
          {
            "name": "entity_type",
            "in": "query",
            "required": false,
            "description": "`company` renvoie l'entreprise associée à ce `vendor_data` ; toute autre valeur, ou aucune valeur, renvoie l'individu. `subject_entity_type` est accepté comme alias lorsque `entity_type` est absent.",
            "schema": {
              "type": "string",
              "enum": [
                "individual",
                "company"
              ],
              "default": "individual"
            },
            "example": "individual"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Nombre maximal d'événements par page. Vaut par défaut 50. Les valeurs supérieures à 1000000 renvoient `400` ; une valeur non numérique, nulle ou négative revient à 50.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "example": 50
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Nombre d'événements à ignorer. Vaut 0 par défaut. Privilégiez l'utilisation de l'URL `next` de la réponse.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "example": 0
          },
          {
            "name": "event_category",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements appartenant à ces catégories. Répétez le paramètre pour plusieurs valeurs (`?event_category=payment&event_category=dispute`) ; un événement correspondant à l'une d'entre elles est renvoyé.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "auth",
                  "session",
                  "gameplay",
                  "bonus",
                  "affiliate",
                  "payment",
                  "dispute",
                  "security",
                  "responsible_gambling",
                  "custom"
                ]
              }
            },
            "example": [
              "payment",
              "dispute"
            ]
          },
          {
            "name": "action_type",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements associés à ces types d'actions (exacts, sensibles à la casse). Répétez pour plusieurs valeurs.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "example": [
              "deposit_completed",
              "chargeback_opened"
            ]
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements associés à ces statuts. Répétez pour plusieurs valeurs.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "ACCEPTED",
                  "APPROVED",
                  "IN_REVIEW",
                  "DECLINED"
                ]
              }
            },
            "example": [
              "IN_REVIEW",
              "DECLINED"
            ]
          },
          {
            "name": "retention_class",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements appartenant à ces classes de conservation. Répétez pour plusieurs valeurs.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "low_value",
                  "standard",
                  "risk_relevant",
                  "monetary_or_compliance"
                ]
              }
            },
            "example": [
              "risk_relevant"
            ]
          },
          {
            "name": "business_vendor_data",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `business.vendor_data` envoyé avec l'événement.",
            "schema": {
              "type": "string"
            },
            "example": "merchant-7"
          },
          {
            "name": "session_id",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur `session.session_id`.",
            "schema": {
              "type": "string"
            },
            "example": "web-session-abc"
          },
          {
            "name": "device_fingerprint",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur `device_context.fingerprint`.",
            "schema": {
              "type": "string"
            },
            "example": "fp-a8c1"
          },
          {
            "name": "ip_address",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur l'adresse IP de l'événement.",
            "schema": {
              "type": "string"
            },
            "example": "203.0.113.42"
          },
          {
            "name": "game_id",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `game_id` promu.",
            "schema": {
              "type": "string"
            },
            "example": "poker-holdem-01"
          },
          {
            "name": "round_id",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `round_id` promu.",
            "schema": {
              "type": "string"
            },
            "example": "round-88231"
          },
          {
            "name": "affiliate_code",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `affiliate_code` promu.",
            "schema": {
              "type": "string"
            },
            "example": "aff-summer"
          },
          {
            "name": "payment_reference_id",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur la référence de paiement (provenant de `transaction_context.payment_reference_id` ou de `payload.payment_reference_id`).",
            "schema": {
              "type": "string"
            },
            "example": "dep_735"
          },
          {
            "name": "counterparty_vendor_data",
            "in": "query",
            "required": false,
            "description": "Correspondance exacte sur le `counterparty_vendor_data` promu.",
            "schema": {
              "type": "string"
            },
            "example": "user-77"
          },
          {
            "name": "matched_only",
            "in": "query",
            "required": false,
            "description": "`true` (également `1` ou `yes`, insensible à la casse) renvoie uniquement les événements pour lesquels au moins une règle a correspondu (`rules_matched_count` supérieur à 0). Toute autre valeur est ignorée.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": true
          },
          {
            "name": "occurred_from",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements dont `occurred_at` est supérieur ou égal à cet instant (inclus). Envoyez une valeur ISO 8601 : `2026-10-01T00:00:00Z`, un décalage explicite avec le `+` encodé en pourcentage (`2026-10-01T02:00:00%2B02:00` ; un `+` non encodé est décodé comme un espace et la valeur ne peut plus être analysée), ou une date seule (`2026-10-01`), ce qui correspond à 00:00:00 UTC de ce jour-là. Une valeur sans décalage est interprétée en UTC. Les valeurs dans tout autre format ne sont pas acceptées.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-10-01T00:00:00Z"
          },
          {
            "name": "occurred_to",
            "in": "query",
            "required": false,
            "description": "Uniquement les événements dont `occurred_at` est inférieur ou égal à cet instant (inclus). Une date seule indique le début de cette journée, donc `occurred_to=2026-10-15` exclut le reste du 15 octobre ; envoyez `2026-10-15T23:59:59Z` pour l'inclure. Envoyez une valeur ISO 8601 : `2026-10-01T00:00:00Z`, un décalage explicite avec le `+` encodé en pourcentage (`2026-10-01T02:00:00%2B02:00` ; un `+` non encodé est décodé comme un espace et la valeur ne peut plus être analysée), ou une date seule (`2026-10-01`), ce qui correspond à 00:00:00 UTC de ce jour-là. Une valeur sans décalage est interprétée en UTC. Les valeurs dans tout autre format ne sont pas acceptées.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-10-17T23:59:59Z"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Correspondance insensible à la casse sur une sous-chaîne de `event_id`, `action_type`, `subject_vendor_data` ou `counterparty_vendor_data`.",
            "schema": {
              "type": "string"
            },
            "example": "chargeback"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/events/subjects/user-42/?entity_type=individual&limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.monitoring_events.retrieve_subject_timeline(\n    \"user-42\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.monitoringEvents.retrieveSubjectTimeline(\"user-42\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.MonitoringEvents.RetrieveSubjectTimelineAutoPaging(ctx, \"user-42\", didit.MonitoringEventsRetrieveSubjectTimelineParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.monitoringEvents().retrieveSubjectTimeline(\"user-42\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->monitoringEvents->retrieveSubjectTimeline('user-42') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.monitoring_events.retrieve_subject_timeline(\"user-42\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.MonitoringEvents.RetrieveSubjectTimelineAsync(\"user-42\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page des événements du sujet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitoringEventPage"
                },
                "examples": {
                  "Individual timeline": {
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "event_uuid": "11111111-2222-3333-4444-555555555555",
                          "event_id": "chargeback-2026-10-16-000318",
                          "event_category": "dispute",
                          "action_type": "chargeback_opened",
                          "occurred_at": "2026-10-16T14:02:11Z",
                          "received_at": "2026-10-16T14:02:12.418230Z",
                          "status": "IN_REVIEW",
                          "score": 60,
                          "subject_vendor_data": "user-42",
                          "subject_entity_type": "individual",
                          "subject_uuid": "66666666-7777-8888-9999-000000000000",
                          "counterparty_vendor_data": null,
                          "session_id": null,
                          "device_fingerprint": null,
                          "ip_address": null,
                          "ip_country": null,
                          "amount": "250.000000000000000000",
                          "currency": "EUR",
                          "game_id": null,
                          "round_id": null,
                          "bonus_id": null,
                          "affiliate_code": null,
                          "payment_reference_id": "dep_735",
                          "retention_class": "monetary_or_compliance",
                          "rules_matched_count": 1,
                          "correlation_pending": false,
                          "is_droppable": false
                        },
                        {
                          "event_uuid": "22222222-3333-4444-5555-666666666666",
                          "event_id": "login-2026-10-15-000912",
                          "event_category": "auth",
                          "action_type": "login",
                          "occurred_at": "2026-10-15T08:30:00.120000Z",
                          "received_at": "2026-10-15T08:30:00.734512Z",
                          "status": "ACCEPTED",
                          "score": 0,
                          "subject_vendor_data": "user-42",
                          "subject_entity_type": "individual",
                          "subject_uuid": "66666666-7777-8888-9999-000000000000",
                          "counterparty_vendor_data": null,
                          "session_id": "web-session-abc",
                          "device_fingerprint": "fp-a8c1",
                          "ip_address": "203.0.113.42",
                          "ip_country": "ES",
                          "amount": null,
                          "currency": null,
                          "game_id": null,
                          "round_id": null,
                          "bonus_id": null,
                          "affiliate_code": null,
                          "payment_reference_id": null,
                          "retention_class": "standard",
                          "rules_matched_count": 0,
                          "correlation_pending": false,
                          "is_droppable": true
                        }
                      ]
                    }
                  },
                  "No events": {
                    "value": {
                      "count": 0,
                      "next": null,
                      "previous": null,
                      "results": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`limit` ou `offset` est supérieur à 1000000. Le corps est un tableau JSON contenant un seul message. Un paramètre `limit` non numérique ou non positif utilise par défaut la valeur de 50 au lieu d'échouer.",
            "content": {
              "application/json": {
                "examples": {
                  "limit too large": {
                    "summary": "limite supérieure à 1000000",
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  },
                  "offset too large": {
                    "summary": "offset supérieur à 1000000",
                    "value": [
                      "offset must not exceed 1000000."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Seule une clé expirée renvoie `401` ; une clé manquante ou invalide renvoie `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Un en-tête `x-api-key` manquant (une clé erronée, révoquée ou expirée renvoie `401`), une clé restreinte sans `transactions: read`, une clé limitée à certains workflows ou à des sessions approuvées (une telle clé n'accède jamais aux données de surveillance des transactions), ou une requête provenant de l'extérieur de la liste d'autorisation IP de la clé.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without access": {
                    "value": {
                      "detail": "This API key has no read access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "IP not allowed": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les requêtes `GET` partagent un quota de 600 requêtes par minute par clé API. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/events/enrichment-metrics/": {
      "get": {
        "summary": "Obtenir les métriques d'enrichissement des événements",
        "description": "Renvoie les compteurs d'ingestion d'événements et d'enrichissement d'IP de votre application pour une période donnée, totalisés sur chaque canal (serveur, lot et appareil), afin que vous puissiez suivre le volume d'événements et confirmer que l'enrichissement est résolu une seule fois par adresse unique plutôt qu'une fois par événement. La période couvre aujourd'hui ainsi que les `days` jours précédents, décomptés selon la date calendaire UTC. Les trois ratios sont nuls lorsque leur dénominateur est égal à zéro. Une clé API avec portée nécessite `transactions: read`. Voir [Enrichissement d'IP](https://docs.didit.me/fr/transaction-monitoring/events#enrichissement-ip).",
        "operationId": "get_monitoring_event_enrichment_metrics",
        "x-didit-sdk": {
          "resource": "monitoring_events",
          "method": "retrieve_enrichment_metrics",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Monitoring Events"
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Durée de la période en jours. Vaut 30 par défaut ; les valeurs sont limitées entre 1 et 365, et une valeur non entière revient à 30. La valeur appliquée est renvoyée sous la forme `period_days`.",
            "schema": {
              "type": "integer",
              "default": 30,
              "minimum": 1,
              "maximum": 365
            },
            "example": 30
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/events/enrichment-metrics/?days=30' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.monitoring_events.retrieve_enrichment_metrics()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.monitoringEvents.retrieveEnrichmentMetrics();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.MonitoringEvents.RetrieveEnrichmentMetrics(ctx, didit.MonitoringEventsRetrieveEnrichmentMetricsParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.monitoringEvents().retrieveEnrichmentMetrics();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->monitoringEvents->retrieveEnrichmentMetrics();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.monitoring_events.retrieve_enrichment_metrics\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.MonitoringEvents.RetrieveEnrichmentMetricsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Compteurs et ratios pour la période.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "events_ingested",
                    "events_rejected",
                    "enrichment_lookups",
                    "enrichment_cache_hits",
                    "enrichment_provider_calls",
                    "enrichment_skipped_low_value",
                    "unique_ips_seen",
                    "period_days",
                    "cache_hit_rate",
                    "unique_ip_ratio",
                    "provider_calls_per_1k_events"
                  ],
                  "properties": {
                    "events_ingested": {
                      "type": "integer",
                      "description": "Nouveaux événements enregistrés. Les rejouements idempotents ne sont pas comptabilisés."
                    },
                    "events_rejected": {
                      "type": "integer",
                      "description": "Éléments rejetés dans les requêtes par lots (flux serveur et appareil). Une requête d'événement unique rejetée n'est pas comptabilisée."
                    },
                    "enrichment_lookups": {
                      "type": "integer",
                      "description": "Événements dont l'adresse IP publique a été résolue, depuis le cache ou récemment."
                    },
                    "enrichment_cache_hits": {
                      "type": "integer",
                      "description": "Recherches servies depuis le cache."
                    },
                    "enrichment_provider_calls": {
                      "type": "integer",
                      "description": "Recherches ayant nécessité une nouvelle résolution de l'adresse."
                    },
                    "enrichment_skipped_low_value": {
                      "type": "integer",
                      "description": "Événements de télémétrie de faible valeur dont l'adresse n'était pas déjà connue. Ils ne déclenchent jamais de nouvelle résolution qui leur soit propre."
                    },
                    "unique_ips_seen": {
                      "type": "integer",
                      "description": "Adresses nécessitant une nouvelle résolution."
                    },
                    "period_days": {
                      "type": "integer",
                      "description": "La valeur `days` appliquée après limitation aux bornes autorisées."
                    },
                    "cache_hit_rate": {
                      "type": "number",
                      "nullable": true,
                      "description": "`enrichment_cache_hits / enrichment_lookups`, arrondi à 4 décimales. Null lorsqu'il n'y a eu aucune recherche."
                    },
                    "unique_ip_ratio": {
                      "type": "number",
                      "nullable": true,
                      "description": "`unique_ips_seen / events_ingested`, arrondi à 4 décimales. Null lorsqu'aucun événement n'a été ingéré."
                    },
                    "provider_calls_per_1k_events": {
                      "type": "number",
                      "nullable": true,
                      "description": "Résolutions fraîches pour 1000 événements ingérés, arrondies à 2 décimales. Null si aucun événement n'a été ingéré."
                    }
                  }
                },
                "examples": {
                  "Last 30 days": {
                    "value": {
                      "events_ingested": 128450,
                      "events_rejected": 214,
                      "enrichment_lookups": 41230,
                      "enrichment_cache_hits": 40118,
                      "enrichment_provider_calls": 1112,
                      "enrichment_skipped_low_value": 74320,
                      "unique_ips_seen": 1112,
                      "period_days": 30,
                      "cache_hit_rate": 0.973,
                      "unique_ip_ratio": 0.0087,
                      "provider_calls_per_1k_events": 8.66
                    }
                  },
                  "No events yet": {
                    "value": {
                      "events_ingested": 0,
                      "events_rejected": 0,
                      "enrichment_lookups": 0,
                      "enrichment_cache_hits": 0,
                      "enrichment_provider_calls": 0,
                      "enrichment_skipped_low_value": 0,
                      "unique_ips_seen": 0,
                      "period_days": 30,
                      "cache_hit_rate": null,
                      "unique_ip_ratio": null,
                      "provider_calls_per_1k_events": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. Seule une clé expirée renvoie `401` ; une clé manquante ou invalide renvoie `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Un en-tête `x-api-key` manquant (une clé erronée, révoquée ou expirée renvoie `401`), une clé restreinte sans `transactions: read`, une clé limitée à certains workflows ou à des sessions approuvées (une telle clé n'accède jamais aux données de surveillance des transactions), ou une requête provenant de l'extérieur de la liste d'autorisation IP de la clé.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without access": {
                    "value": {
                      "detail": "This API key has no read access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "IP not allowed": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les requêtes `GET` partagent un quota de 600 requêtes par minute par clé API. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/events/{event_uuid}/delete/": {
      "delete": {
        "summary": "Supprimer l'événement de surveillance",
        "description": "Supprime définitivement un événement de surveillance ainsi que ses exécutions de règles, notes et liens d'étiquettes, par exemple un événement envoyé par erreur. Après le `204`, l'événement disparaît de toute lecture (la récupération renvoie `404`, et il n'apparaît plus dans la liste ni dans la chronologie du sujet), la suppression est irréversible, et son `event_id` peut être réutilisé pour un nouvel événement. Ne sont pas affectés : l'utilisateur ou l'entreprise auquel ou à laquelle l'événement a été rattaché, les dossiers ouverts par une règle, les entrées de liste ajoutées par une règle, ainsi que les scores et statuts déjà appliqués à d'autres événements. Pour effacer tout ce qui concerne une personne ou une entreprise, supprimez plutôt l'utilisateur ou l'entreprise, ce qui supprime également ses événements. Une clé API restreinte nécessite `transactions: write`.",
        "operationId": "delete_monitoring_event",
        "x-didit-sdk": {
          "resource": "monitoring_events",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Monitoring Events"
        ],
        "parameters": [
          {
            "name": "event_uuid",
            "in": "path",
            "required": true,
            "description": "Identifiant Didit de l'événement (`event_uuid` issu de la réponse de création, de lot, de liste ou de chronologie), et non votre propre `event_id`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-2222-3333-4444-555555555555"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/events/11111111-2222-3333-4444-555555555555/delete/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.monitoring_events.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.monitoringEvents.delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.MonitoringEvents.Delete(ctx, \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.monitoringEvents().delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->monitoringEvents->delete('11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.monitoring_events.delete(\"11111111-2222-3333-4444-555555555555\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.MonitoringEvents.DeleteAsync(\"11111111-2222-3333-4444-555555555555\");"
          }
        ],
        "responses": {
          "204": {
            "description": "L'événement a été supprimé. Aucun corps."
          },
          "401": {
            "description": "La clé API restreinte a expiré. Seule une clé expirée renvoie `401` ; une clé manquante ou invalide renvoie `403`.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Un en-tête `x-api-key` manquant (une clé erronée, révoquée ou expirée renvoie `401`), une clé restreinte sans `transactions: write`, une clé limitée à certains workflows ou à des sessions approuvées (une telle clé n'accède jamais aux données de surveillance des transactions), ou une requête provenant de l'extérieur de la liste d'autorisation IP de la clé.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing or invalid API key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without access": {
                    "value": {
                      "detail": "This API key has no write access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "IP not allowed": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucun événement avec cet `event_uuid` n'existe dans l'application : il n'a jamais été enregistré, il a été supprimé ou il appartient à une autre application. Un segment de chemin qui n'est pas un UUID ne correspond pas à la route et renvoie également `404`.",
            "content": {
              "application/json": {
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No MonitoringEvent matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : les requêtes d'écriture (`POST`, `PATCH`, `DELETE`) partagent un quota de 300 requêtes par minute par clé API. Attendez `Retry-After` secondes, puis réessayez.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/kyb/parties/{partyUuid}/regenerate/": {
      "post": {
        "summary": "Régénérer la session KYC d'une personne clé",
        "description": "Attribuer à une partie de type personnes clés d'une session de vérification d'entreprise (KYB) une nouvelle session KYC individuelle après la suppression de la précédente ou son expiration avant que la personne ne l'ait commencée, afin que le contrôle des personnes clés puisse à nouveau se terminer ; n'envoyez aucun corps de requête. Cela fonctionne lorsque la session KYC de la partie a été supprimée (`kyc_session_deleted: true`) ou a expiré avant que la personne ne l'ait commencée (`Expired`, jamais commencée). Une session encore en cours ou qui s'est terminée sous tout autre statut (`Approved`, `Declined`, `In Review`, `Abandoned`, ...) renvoie `409`, sauf si elle a été supprimée. Une partie qui n'en a jamais eu ou une partie de type entreprise renvoie toujours `409`. Didit crée une nouvelle session KYC hébergée avec le workflow avec lequel la partie a été vérifiée (sa dernière version publiée) ou, lorsqu'il n'est plus connu, le workflow que vos paramètres de personnes clés attribuent au rôle de la partie, afin que son lien reste valide pendant la durée d'expiration de session de ce workflow KYC ; il envoie le lien par e-mail à la partie lorsqu'une adresse e-mail est enregistrée, efface `is_skipped` et recalcule le contrôle des personnes clés ainsi que le statut de la session d'entreprise. Il envoie ensuite un [webhook](https://docs.didit.me/fr/integration/webhooks) `data.updated` pour la session d'entreprise avec le déclencheur `console_key_people_regenerate` ; pour exempter la partie à la place, utilisez `PATCH /v3/session/{sessionId}/kyb/parties/{partyUuid}/`. Une clé API restreinte nécessite `decisions: write`, et sans `sessions: write`, elle reçoit `kyc_session_url` avec la valeur `null`. Les sessions supprimées sont éligibles même si la personne avait déjà commencé ou terminé la vérification. Les sessions importées ne sont pas éligibles par expiration ; elles doivent avoir été supprimées.",
        "operationId": "post_v3_session_kyb_party_regenerate",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "regenerate_kyb_party",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session parente de Vérification d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "partyUuid",
            "in": "path",
            "required": true,
            "description": "UUID de la partie « personnes clés » (`key_people_checks[].submitted.parties[].uuid` sur la décision de la session d'entreprise). Doit appartenir à la session référencée par `sessionId`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/session/33333333-4444-5555-6666-777777777777/kyb/parties/0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41/regenerate/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.regenerate_kyb_party(\n    \"33333333-4444-5555-6666-777777777777\",\n    \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.regenerateKybParty(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.RegenerateKYBParty(ctx, \"33333333-4444-5555-6666-777777777777\", \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().regenerateKybParty(\"33333333-4444-5555-6666-777777777777\", \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->regenerateKybParty('33333333-4444-5555-6666-777777777777', '0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.regenerate_kyb_party(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.RegenerateKybPartyAsync(\"33333333-4444-5555-6666-777777777777\", \"0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Nouvelle session KYC créée. Renvoie la partie mise à jour avec sa nouvelle session enfant, qui expire après le délai d'expiration de session de son workflow KYC.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KYBKeyPeopleParty"
                },
                "example": {
                  "uuid": "0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41",
                  "entity_type": "person",
                  "source": "USER",
                  "name": "Jane Smith",
                  "first_name": "Jane",
                  "last_name": "Smith",
                  "company_name": null,
                  "registration_number": null,
                  "email": "user@example.com",
                  "nationality": "GB",
                  "phone_number": null,
                  "date_of_birth": "1980-05-04",
                  "position": "Director",
                  "custom_fields": {},
                  "is_active": true,
                  "is_skipped": false,
                  "requires_verification": true,
                  "roles": [
                    {
                      "role": "director",
                      "ownership_percent": null,
                      "voting_percent": null
                    }
                  ],
                  "kyc_session_id": "55555555-6666-7777-8888-999999999999",
                  "kyc_session_status": "Not Started",
                  "kyc_session_url": "https://verify.didit.me/session/abc123def456",
                  "kyc_session_deleted": false,
                  "kyb_sub_session_id": null,
                  "kyb_sub_session_status": null,
                  "kyb_sub_session_url": null,
                  "kyb_sub_session_deleted": false,
                  "verification_workflow_type": "kyc",
                  "verification_workflow_id": "12121212-3434-5656-7878-909090909090",
                  "verification_workflow_label": "Key People KYC",
                  "verification_workflow_features": [
                    {
                      "feature": "ID_VERIFICATION",
                      "status": "Not Finished"
                    },
                    {
                      "feature": "LIVENESS",
                      "status": "Not Finished"
                    },
                    {
                      "feature": "AML",
                      "status": "Not Finished"
                    }
                  ],
                  "didit_internal_id": null
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée ou se trouve en dehors des limites d'une clé restreinte ; aucune partie avec cet UUID n'existe dans votre application ; ou la partie appartient à une autre session. Chaque cas possède son propre `detail`. La recherche de session s'exécute avant la vérification des identifiants, donc un `sessionId` inconnu renvoie `404` même sans clé valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID n'existe, ou elle a été supprimée",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside key limits": {
                    "summary": "La session se trouve en dehors des limites de workflow ou réservées aux sessions approuvées d'une clé restreinte",
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "Unknown party": {
                    "summary": "Aucune partie avec cet UUID dans votre application",
                    "value": {
                      "detail": "No BusinessParty matches the given query."
                    }
                  },
                  "Party of another session": {
                    "summary": "partyUuid existe mais appartient à une session différente",
                    "value": {
                      "detail": "Party does not belong to the given session."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "La partie n'a aucune session KYC éligible à remplacer. Sauf si elle a été supprimée, une session toujours en cours ou terminée avec un autre statut (`Approved`, `Declined`, `In Review`, `Abandoned`, ...) ne peut pas être régénérée. Une partie qui n'en a jamais eu ou une partie représentant une entreprise renvoie également `409`. Une session éligible a été supprimée ou a expiré avant que la personne ne la commence. Les sessions supprimées restent éligibles même si la personne avait déjà commencé ou terminé la vérification. Les sessions importées ne sont pas éligibles par expiration ; elles doivent avoir été supprimées. Créez une branche selon `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "detail",
                    "code"
                  ],
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "kyb_party_kyc_session_not_deleted"
                      ],
                      "description": "Code d'erreur stable lisible par machine."
                    }
                  }
                },
                "example": {
                  "detail": "This party's KYC session is still live (it has neither been deleted nor expired without starting), so it cannot be regenerated.",
                  "code": "kyb_party_kyc_session_not_deleted"
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 300 requêtes d'écriture (POST, PATCH, DELETE) par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/transactions/{transaction_id}/notes/": {
      "get": {
        "summary": "Lister les notes de transaction",
        "description": "Lister les notes associées à une transaction surveillée, de la plus récente à la plus ancienne (`created_at` décroissant) : les notes que vous ajoutez via l'API, les notes et changements de statut effectués par les réviseurs dans la Console, ainsi que les notes que Didit ajoute automatiquement (action `add_note` d'une règle, ou problème lors de la création de la session de vérification de l'action utilisateur), qui portent le `actor_name` `Rule Engine`. `metadata` permet de distinguer les types de notes.\n\nLa réponse est paginée avec `limit` et `offset`. `count` est exact jusqu'à 100 et plafonné à 100 au-delà, suivez donc `next` jusqu'à ce qu'il soit `null` au lieu de calculer les pages à partir de `count`. Il s'agit d'une lecture sans effet secondaire.\n\nUne clé API restreinte nécessite `transactions: read` ; une clé limitée à certains workflows ou aux sessions approuvées ne peut pas appeler cet endpoint. Les réviseurs voient la même liste sous **Notes** dans le [détail de la transaction](https://docs.didit.me/fr/transaction-monitoring/console#détail-d’une-transaction).",
        "operationId": "list_transaction_notes",
        "x-didit-sdk": {
          "resource": "transactions.notes",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID de transaction Didit : le `uuid` renvoyé par `POST /v3/transactions/` et `GET /v3/transactions/`. Votre propre `txn_id` n'est pas accepté.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "abcdef12-3456-7890-abcd-ef1234567890"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "description": "Nombre de notes par page. La valeur par défaut est 50. Une valeur qui n'est pas un entier positif revient à 50 ; une valeur supérieure à 1000000 renvoie `400`."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "description": "Position de départ (base zéro) de la première note à retourner. Privilégiez l'utilisation de `next`. Une valeur qui n'est pas un nombre entier revient par défaut à 0 ; une valeur supérieure à 1000000 retourne `400`."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/transactions/abcdef12-3456-7890-abcd-ef1234567890/notes/?limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.transactions.notes.list(\n    \"abcdef12-3456-7890-abcd-ef1234567890\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.transactions.notes.list(\"abcdef12-3456-7890-abcd-ef1234567890\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Transactions.Notes.ListAutoPaging(ctx, \"abcdef12-3456-7890-abcd-ef1234567890\", didit.TransactionsNotesListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.transactions().notes().list(\"abcdef12-3456-7890-abcd-ef1234567890\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->transactions->notes->list('abcdef12-3456-7890-abcd-ef1234567890') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.transactions.notes.list(\"abcdef12-3456-7890-abcd-ef1234567890\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Transactions.Notes.ListAsync(\"abcdef12-3456-7890-abcd-ef1234567890\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de notes, les plus récentes en premier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de notes sur la transaction : exact jusqu'à 100, plafonné à 100 au-delà. Suivez `next` au lieu de calculer les pages à partir de cette valeur."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TransactionNote"
                      }
                    }
                  }
                },
                "examples": {
                  "API, Console and rule notes": {
                    "value": {
                      "count": 3,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "c1111111-2222-4333-8444-555555555555",
                          "note": "Customer confirmed the withdrawal by phone.",
                          "actor_email": null,
                          "actor_name": null,
                          "metadata": {
                            "mentioned_emails": [
                              "analyst@example.com"
                            ]
                          },
                          "created_at": "2026-10-16T10:05:12.481203Z"
                        },
                        {
                          "uuid": "c2222222-3333-4444-8555-666666666666",
                          "note": "Status changed from IN_REVIEW to APPROVED. Reason: Source of funds verified",
                          "actor_email": "reviewer@example.com",
                          "actor_name": "Alex Reviewer",
                          "metadata": {
                            "type": "status_change",
                            "previous_status": "IN_REVIEW",
                            "new_status": "APPROVED",
                            "reason_code": "SOF_VERIFIED",
                            "reason_label": "Source of funds verified"
                          },
                          "created_at": "2026-10-15T17:22:40.103911Z"
                        },
                        {
                          "uuid": "c3333333-4444-4555-8666-777777777777",
                          "note": "Large withdrawal to a new wallet: check the source of funds.",
                          "actor_email": null,
                          "actor_name": "Rule Engine",
                          "metadata": {
                            "rule_uuid": "d1111111-2222-4333-8444-555555555555",
                            "source": "rule_action"
                          },
                          "created_at": "2026-10-15T08:42:12.004518Z"
                        }
                      ]
                    }
                  },
                  "No notes yet": {
                    "value": {
                      "count": 0,
                      "next": null,
                      "previous": null,
                      "results": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`limit` ou `offset` est supérieur à 1000000. Le corps est un tableau JSON de messages, pas un objet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "examples": {
                  "Limit too large": {
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  },
                  "Offset too large": {
                    "value": [
                      "offset must not exceed 1000000."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré. Seule une clé créée avec une date d'expiration peut expirer ; après cette date, chaque requête effectuée avec celle-ci renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Une clé manquante reçoit le message générique ; une clé erronée, révoquée ou expirée reçoit `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without transactions read": {
                    "value": {
                      "detail": "This API key has no read access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the key's IP list": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune transaction avec cet UUID n'existe dans l'application (jamais créée, supprimée ou détenue par une autre application). Un `transaction_id` qui n'est pas un UUID n'atteint pas l'API : il renvoie une page HTML `404` au lieu de ce corps JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No Transaction matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 600 requêtes GET par minute avec cette clé API. Attendez le nombre de secondes indiqué dans `Retry-After`, puis réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes avant la réinitialisation de la fenêtre actuelle d'une minute.",
                "schema": {
                  "type": "integer",
                  "example": 23
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées par minute dans ce budget.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix auquel la fenêtre se réinitialise.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Créer une note de transaction",
        "description": "Ajoutez une note en texte brut à la chronologie d'examen d'une transaction surveillée, où les réviseurs de la Console peuvent la voir. Une note apporte du contexte et ne constitue pas une décision : le `status`, le `score` et les alertes de la transaction ne changent pas, aucun webhook n'est envoyé et rien n'est facturé. Le champ `activities` de la transaction reçoit une entrée `TRANSACTION_NOTE_ADDED`.\n\nLes notes créées avec une clé API n'ont pas d'auteur : `actor_email` et `actor_name` sont à `null`, indiquez donc l'auteur dans le texte si vous en avez besoin. Chaque adresse dans `mentioned_emails` doit appartenir à un membre de votre organisation, sinon l'ensemble de la requête échoue avec une erreur `400` ; les mentions sont enregistrées en minuscules et dédupliquées, et cet endpoint n'envoie pas de notification aux membres mentionnés.\n\nChaque appel crée une nouvelle note, donc réessayer une requête dont le délai d'attente a expiré peut l'ajouter deux fois : listez les notes avant de réessayer. Il n'existe aucun endpoint API pour modifier ou supprimer une note. Une clé API avec restriction de portée nécessite `transactions: write` ; une clé limitée à certains workflows ou à des sessions approuvées ne peut pas appeler cet endpoint.",
        "operationId": "create_transaction_note",
        "x-didit-sdk": {
          "resource": "transactions.notes",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID de transaction Didit : le `uuid` renvoyé par `POST /v3/transactions/` et `GET /v3/transactions/`. Votre propre `txn_id` n'est pas accepté.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "abcdef12-3456-7890-abcd-ef1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "note"
                ],
                "properties": {
                  "note": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Note en texte brut. Les espaces de début et de fin sont supprimés et une note vide est rejetée. Aucune limite de longueur."
                  },
                  "mentioned_emails": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    },
                    "default": [],
                    "description": "E-mails des membres de votre organisation à mentionner. Chacun doit être un e-mail valide d'un membre de l'organisation."
                  }
                }
              },
              "examples": {
                "Note with a mention": {
                  "value": {
                    "note": "Customer confirmed the withdrawal by phone.",
                    "mentioned_emails": [
                      "analyst@example.com"
                    ]
                  }
                },
                "Plain note": {
                  "value": {
                    "note": "Source of funds document requested by email."
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/transactions/abcdef12-3456-7890-abcd-ef1234567890/notes/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"note\": \"Customer confirmed the withdrawal by phone.\", \"mentioned_emails\": [\"analyst@example.com\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.transactions.notes.create(\n    \"abcdef12-3456-7890-abcd-ef1234567890\",\n    note=\"Customer confirmed the withdrawal by phone.\",\n    mentioned_emails=[\"analyst@example.com\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.transactions.notes.create(\"abcdef12-3456-7890-abcd-ef1234567890\", {\n  note: \"Customer confirmed the withdrawal by phone.\",\n  mentioned_emails: [\"analyst@example.com\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.Notes.Create(ctx, \"abcdef12-3456-7890-abcd-ef1234567890\", didit.TransactionsNotesCreateParams{\n\tNote:            \"Customer confirmed the withdrawal by phone.\",\n\tMentionedEmails: didit.Some([]string{\"analyst@example.com\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.TransactionsNotesCreateParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.transactions().notes().create(\"abcdef12-3456-7890-abcd-ef1234567890\", TransactionsNotesCreateParams.builder()\n        .note(\"Customer confirmed the withdrawal by phone.\")\n        .mentionedEmails(List.of(\"analyst@example.com\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->transactions->notes->create('abcdef12-3456-7890-abcd-ef1234567890', [\n    'note' => 'Customer confirmed the withdrawal by phone.',\n    'mentioned_emails' => ['analyst@example.com'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.transactions.notes.create(\n  \"abcdef12-3456-7890-abcd-ef1234567890\",\n  note: \"Customer confirmed the withdrawal by phone.\",\n  mentioned_emails: [\"analyst@example.com\"]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Transactions.Notes.CreateAsync(\"abcdef12-3456-7890-abcd-ef1234567890\", new TransactionsNotesCreateParams\n{\n    Note = \"Customer confirmed the withdrawal by phone.\",\n    MentionedEmails = new string[] { \"analyst@example.com\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "La note a été créée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionNote"
                },
                "examples": {
                  "Created": {
                    "value": {
                      "uuid": "c1111111-2222-4333-8444-555555555555",
                      "note": "Customer confirmed the withdrawal by phone.",
                      "actor_email": null,
                      "actor_name": null,
                      "metadata": {
                        "mentioned_emails": [
                          "analyst@example.com"
                        ]
                      },
                      "created_at": "2026-10-16T10:05:12.481203Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le corps est invalide : `note` manquant, nul ou vide, adresse invalide dans `mentioned_emails` (erreurs indexées par position dans la liste), ou adresse mentionnée qui ne correspond pas à un membre de votre organisation. Rien n'est créé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Erreurs de champ associées par nom de champ.",
                  "additionalProperties": {}
                },
                "examples": {
                  "Missing note": {
                    "value": {
                      "note": [
                        "This field is required."
                      ]
                    }
                  },
                  "Blank note": {
                    "value": {
                      "note": [
                        "This field may not be blank."
                      ]
                    }
                  },
                  "Invalid email": {
                    "value": {
                      "mentioned_emails": {
                        "0": [
                          "Enter a valid email address."
                        ]
                      }
                    }
                  },
                  "Not an organization member": {
                    "value": {
                      "mentioned_emails": [
                        "Mentioned users must belong to this organization and have access to this application."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré. Seule une clé créée avec une date d'expiration peut expirer ; après cette date, chaque requête effectuée avec celle-ci renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Une clé manquante reçoit le message générique ; une clé erronée, révoquée ou expirée reçoit `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without transactions write": {
                    "value": {
                      "detail": "This API key has no write access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the key's IP list": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune transaction avec cet UUID n'existe dans l'application (jamais créée, supprimée ou détenue par une autre application). Un `transaction_id` qui n'est pas un UUID n'atteint pas l'API : il renvoie une page HTML `404` au lieu de ce corps JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No Transaction matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 300 requêtes d'écriture par minute avec cette clé API. Attendez le nombre de secondes indiqué dans `Retry-After`, puis réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes avant la réinitialisation de la fenêtre actuelle d'une minute.",
                "schema": {
                  "type": "integer",
                  "example": 23
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées par minute dans ce budget.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix auquel la fenêtre se réinitialise.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/transactions/{transaction_id}/related/": {
      "get": {
        "summary": "Lister les transactions associées",
        "description": "Lister les autres transactions dans votre application qui impliquent les mêmes personnes ou entreprises que celle-ci. Une transaction est liée lorsque l'une de ses parties, quel que soit son rôle, possède le même `vendor_data` que l'une des parties de cette transaction. La transaction elle-même n'est jamais renvoyée, et les parties sans `vendor_data` sont ignorées : si aucune des parties de cette transaction n'en possède un, le résultat est toujours vide.\n\nLes résultats utilisent la structure résumée de `GET /v3/transactions/`, les plus récentes en premier (`txn_date`, puis `created_at`). Paginés avec `limit` et `offset` ; `count` est exact jusqu'à 100 et plafonné à 100 au-delà, suivez donc `next` jusqu'à ce qu'il soit `null`.\n\nUne clé API restreinte nécessite `transactions: read` ; une clé limitée à certains workflows ou à des sessions approuvées ne peut pas appeler cet endpoint. Envoyez le même `vendor_data` pour la même personne ou entreprise sur chaque [transaction](https://docs.didit.me/fr/transaction-monitoring/transactions#sujet-et-contrepartie) pour rendre cette liste exhaustive.",
        "operationId": "list_related_transactions",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "list_related",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Transactions"
        ],
        "parameters": [
          {
            "name": "transaction_id",
            "in": "path",
            "required": true,
            "description": "UUID de transaction Didit : le `uuid` renvoyé par `POST /v3/transactions/` et `GET /v3/transactions/`. Votre propre `txn_id` n'est pas accepté.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "abcdef12-3456-7890-abcd-ef1234567890"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000
            },
            "description": "Nombre de transactions par page. La valeur par défaut est 50. Une valeur qui n'est pas un entier positif revient à 50 ; une valeur supérieure à 1000000 renvoie `400`."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000
            },
            "description": "Position de départ (base zéro) de la première transaction à retourner. Privilégiez l'utilisation de `next`. Une valeur qui n'est pas un nombre entier revient par défaut à 0 ; une valeur supérieure à 1000000 retourne `400`."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/transactions/abcdef12-3456-7890-abcd-ef1234567890/related/?limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.transactions.list_related(\n    \"abcdef12-3456-7890-abcd-ef1234567890\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.transactions.listRelated(\"abcdef12-3456-7890-abcd-ef1234567890\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Transactions.ListRelatedAutoPaging(ctx, \"abcdef12-3456-7890-abcd-ef1234567890\", didit.TransactionsListRelatedParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.transactions().listRelated(\"abcdef12-3456-7890-abcd-ef1234567890\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->transactions->listRelated('abcdef12-3456-7890-abcd-ef1234567890') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.transactions.list_related(\"abcdef12-3456-7890-abcd-ef1234567890\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Transactions.ListRelatedAsync(\"abcdef12-3456-7890-abcd-ef1234567890\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de transactions associées, les plus récentes en premier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre de transactions associées : exact jusqu'à 100, plafonné à 100 au-delà. Suivez `next` au lieu de calculer les pages à partir de cette valeur."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL absolue de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TransactionSummary"
                      }
                    }
                  }
                },
                "examples": {
                  "One related transaction": {
                    "value": {
                      "count": 1,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "abcdef99-3456-4890-abcd-ef1234567890",
                          "transaction_number": 4087,
                          "txn_id": "your-txn-2026-10-02-017",
                          "transaction_type": "finance",
                          "action_type": "deposit",
                          "status": "APPROVED",
                          "source": "LIVE",
                          "direction": "INBOUND",
                          "amount": "250",
                          "currency": "EUR",
                          "currency_type": "fiat",
                          "preferred_currency_amount": "270.08",
                          "preferred_currency_code": "USD",
                          "payment_details": "Card top-up",
                          "txn_date": "2026-10-02T14:10:00Z",
                          "created_at": "2026-10-02T14:10:03.512244Z",
                          "score": 12,
                          "severity": "LOW",
                          "decision_reason_code": null,
                          "decision_reason_label": null,
                          "tags": [],
                          "subject_name": "Maria Garcia",
                          "subject_vendor_data": "user-12345",
                          "subject_type": "user",
                          "subject_uuid": "e1111111-2222-4333-8444-555555555555",
                          "counterparty_name": null,
                          "counterparty_vendor_data": null,
                          "counterparty_country": null,
                          "subject_country": "ESP",
                          "assigned_to_name": null,
                          "travel_rule_status": null,
                          "application_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                          "application_name": "Production app",
                          "organization_id": "11111111-2222-3333-4444-555555555555",
                          "organization_name": "Example Org"
                        }
                      ]
                    }
                  },
                  "No party has vendor_data": {
                    "value": {
                      "count": 0,
                      "next": null,
                      "previous": null,
                      "results": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`limit` ou `offset` est supérieur à 1000000. Le corps est un tableau JSON de messages, pas un objet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "examples": {
                  "Limit too large": {
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  },
                  "Offset too large": {
                    "value": [
                      "offset must not exceed 1000000."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré. Seule une clé créée avec une date d'expiration peut expirer ; après cette date, chaque requête effectuée avec celle-ci renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Une clé manquante reçoit le message générique ; une clé erronée, révoquée ou expirée reçoit `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without transactions read": {
                    "value": {
                      "detail": "This API key has no read access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the key's IP list": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune transaction avec cet UUID n'existe dans l'application (jamais créée, supprimée ou détenue par une autre application). Un `transaction_id` qui n'est pas un UUID n'atteint pas l'API : il renvoie une page HTML `404` au lieu de ce corps JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No Transaction matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 600 requêtes GET par minute avec cette clé API. Attendez le nombre de secondes indiqué dans `Retry-After`, puis réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes avant la réinitialisation de la fenêtre actuelle d'une minute.",
                "schema": {
                  "type": "integer",
                  "example": 23
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées par minute dans ce budget.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix auquel la fenêtre se réinitialise.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/businesses/{business_session_id}/pdf/": {
      "get": {
        "summary": "Télécharger un rapport PDF de session d'entreprise",
        "description": "Générez le rapport PDF d'une session de Vérification d'entreprise (KYB) : données du registre des sociétés, personnes clés et bénéficiaires effectifs, documents, résultats AML et les autres fonctionnalités du workflow, ainsi que les tags de la session et l'activité d'examen. Avec la personnalisation en marque blanche activée, le rapport inclut votre logo et l'URL de votre politique de confidentialité. Le corps de la réponse est le PDF lui-même (`application/pdf`), et non du JSON.\n\nLa session doit être à l'état `Approved`, `Declined` ou `In Review` ; tout autre statut renvoie un code `403`, attendez donc d'abord le [webhook](https://docs.didit.me/fr/integration/webhooks) `status.updated`. Le rapport est généré à chaque appel et rien n'est facturé ; stockez donc le fichier au lieu de le récupérer de manière répétée. `GET /v3/session/{sessionId}/generate-pdf/` génère le même type de rapport à partir du seul identifiant de session.\n\nUn rapport PDF est considéré comme un média : une clé API restreinte nécessite `businesses: read` et `media: read`, et une clé limitée à certains workflows ou aux sessions approuvées ne peut pas l'appeler.",
        "operationId": "get_business_session_pdf",
        "x-didit-sdk": {
          "resource": "businesses",
          "method": "generate_session_pdf",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Businesses"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation.",
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application. Doit être l'application à laquelle appartient la clé API : une clé utilisée sur toute autre application reçoit une erreur `403`.",
            "example": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
          },
          {
            "name": "business_session_id",
            "in": "path",
            "required": true,
            "description": "`session_id` de la session de Vérification d'entreprise (KYB), tel que renvoyé lors de la création de la session. Une session d'une autre application renvoie `404`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "22222222-3333-4444-5555-666666666666"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl --fail -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/businesses/22222222-3333-4444-5555-666666666666/pdf/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  --output business_report.pdf"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\ncontent = client.businesses.generate_session_pdf(\n    \"22222222-3333-4444-5555-666666666666\",\n)\nwith open(\"download.pdf\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst content = await didit.businesses.generateSessionPdf(\"22222222-3333-4444-5555-666666666666\");\nawait writeFile(\"download.pdf\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresp, err := client.Businesses.GenerateSessionPDF(ctx, \"22222222-3333-4444-5555-666666666666\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.businesses().generateSessionPdf(\"22222222-3333-4444-5555-666666666666\")\n        .writeTo(Path.of(\"download.pdf\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$content = $didit->businesses->generateSessionPdf('22222222-3333-4444-5555-666666666666');\n$content->saveTo('download.pdf');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ncontent = didit.businesses.generate_session_pdf(\"22222222-3333-4444-5555-666666666666\")\nFile.binwrite(\"download.pdf\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar content = await client.Businesses.GenerateSessionPdfAsync(\"22222222-3333-4444-5555-666666666666\");\nawait content.SaveToAsync(\"download.pdf\");"
          }
        ],
        "responses": {
          "200": {
            "description": "Le PDF généré, renvoyé directement au format binaire `application/pdf`.",
            "headers": {
              "Content-Disposition": {
                "description": "Toujours `attachment; filename=business_{business_session_id}.pdf`.",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=business_22222222-3333-4444-5555-666666666666.pdf"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré. Seule une clé créée avec une date d'expiration peut expirer ; après cette date, chaque requête effectuée avec celle-ci renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée ou la session n'est pas terminée. Lisez `detail` : une session qui n'est pas `Approved`, `Declined` ou `In Review`, une clé API manquante (une clé erronée, révoquée ou expirée reçoit `401`), un `application_id` qui n'est pas celui de l'application de la clé, une clé restreinte sans `media: read` ou `businesses: read`, une clé limitée aux workflows ou aux sessions approuvées, ou une requête provenant de l'extérieur de la liste d'IP de la clé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Session not finished": {
                    "value": {
                      "detail": "You can only generate a PDF for sessions in review, declined or approved."
                    }
                  },
                  "Missing or invalid key": {
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Another application": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without media read": {
                    "value": {
                      "detail": "This API key has no read access to media."
                    }
                  },
                  "Scoped key without businesses read": {
                    "value": {
                      "detail": "This API key has no read access to companies."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the key's IP list": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session d'entreprise avec cet ID n'existe dans l'application (jamais créée, supprimée ou détenue par une autre application). Une valeur qui n'est pas un UUID renvoie une page HTML `404` au lieu de ce corps JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "Business session not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 600 requêtes GET par minute avec cette clé API. Attendez le nombre de secondes indiqué dans `Retry-After`, puis réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes avant la réinitialisation de la fenêtre actuelle d'une minute.",
                "schema": {
                  "type": "integer",
                  "example": 23
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées par minute dans ce budget.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix auquel la fenêtre se réinitialise.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/transactions/{transaction_uuid}/pdf/": {
      "get": {
        "summary": "Télécharger un rapport PDF de transaction",
        "description": "Générez le rapport PDF d'une transaction surveillée : vue d'ensemble et verdict, parties et moyens de paiement, propriétés personnalisées, alertes et exécutions de règles, résultats de filtrage et Travel Rule, récapitulatif du réseau, ventilation des coûts, jusqu'à 50 transactions associées et les 20 entrées d'activité les plus récentes. Le corps de la réponse est le PDF lui-même (`application/pdf`), et non du JSON.\n\nLe rapport est généré à partir des données actuelles de la transaction à chaque appel ; demandez-le donc à nouveau après un changement de statut. Rien n'est stocké et rien n'est facturé. La génération peut prendre quelques secondes, prévoyez donc un délai d'expiration client généreux.\n\nCet endpoint réside sur un chemin propre à l'application : indiquez l'identifiant de votre organisation et l'identifiant de l'application à laquelle appartient votre clé API dans l'URL ([trouver l'identifiant de votre organisation](https://docs.didit.me/fr/getting-started/api-authentication#trouver-l’id-de-votre-organisation)). Un rapport PDF est considéré comme un média : une clé API restreinte nécessite `media: read` et `transactions: read`, et une clé limitée à certains workflows ou aux sessions approuvées ne peut pas l'appeler.",
        "operationId": "get_transaction_pdf",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "generate_pdf",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Transactions"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation.",
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application. Doit être l'application à laquelle appartient la clé API : une clé utilisée sur toute autre application reçoit une erreur `403`.",
            "example": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
          },
          {
            "name": "transaction_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de transaction Didit : le `uuid` renvoyé par `POST /v3/transactions/` et `GET /v3/transactions/`. Votre propre `txn_id` n'est pas accepté.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "abcdef12-3456-7890-abcd-ef1234567890"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl --fail -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/transactions/abcdef12-3456-7890-abcd-ef1234567890/pdf/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  --output transaction_report.pdf"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\ncontent = client.transactions.generate_pdf(\n    \"abcdef12-3456-7890-abcd-ef1234567890\",\n)\nwith open(\"download.pdf\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst content = await didit.transactions.generatePdf(\"abcdef12-3456-7890-abcd-ef1234567890\");\nawait writeFile(\"download.pdf\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresp, err := client.Transactions.GeneratePDF(ctx, \"abcdef12-3456-7890-abcd-ef1234567890\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.transactions().generatePdf(\"abcdef12-3456-7890-abcd-ef1234567890\")\n        .writeTo(Path.of(\"download.pdf\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$content = $didit->transactions->generatePdf('abcdef12-3456-7890-abcd-ef1234567890');\n$content->saveTo('download.pdf');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ncontent = didit.transactions.generate_pdf(\"abcdef12-3456-7890-abcd-ef1234567890\")\nFile.binwrite(\"download.pdf\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar content = await client.Transactions.GeneratePdfAsync(\"abcdef12-3456-7890-abcd-ef1234567890\");\nawait content.SaveToAsync(\"download.pdf\");"
          }
        ],
        "responses": {
          "200": {
            "description": "Le PDF généré, renvoyé directement au format binaire `application/pdf`.",
            "headers": {
              "Content-Disposition": {
                "description": "Toujours `attachment; filename=transaction_{transaction_uuid}.pdf`.",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=transaction_abcdef12-3456-7890-abcd-ef1234567890.pdf"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré. Seule une clé créée avec une date d'expiration peut expirer ; après cette date, chaque requête effectuée avec celle-ci renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Consultez `detail` : une clé API manquante (une clé erronée, révoquée ou expirée renvoie `401`), un `application_id` qui n'est pas celui de l'application de la clé, une clé avec restriction de portée sans `media: read` ou `transactions: read`, une clé limitée à des workflows ou à des sessions approuvées, ou une requête provenant de l'extérieur de la liste d'adresses IP de la clé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Another application": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without media read": {
                    "value": {
                      "detail": "This API key has no read access to media."
                    }
                  },
                  "Scoped key without transactions read": {
                    "value": {
                      "detail": "This API key has no read access to transactions."
                    }
                  },
                  "Key limited to workflows or approved sessions": {
                    "value": {
                      "detail": "This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint."
                    }
                  },
                  "Outside the key's IP list": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune transaction avec cet UUID n'existe dans l'application (jamais créée, supprimée ou détenue par une autre application). Un `transaction_uuid` qui n'est pas un UUID n'atteint pas l'API : il renvoie une page HTML `404` au lieu de ce corps JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Not found": {
                    "value": {
                      "detail": "No Transaction matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 600 requêtes GET par minute avec cette clé API. Attendez le nombre de secondes indiqué dans `Retry-After`, puis réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes avant la réinitialisation de la fenêtre actuelle d'une minute.",
                "schema": {
                  "type": "integer",
                  "example": 23
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées par minute dans ce budget.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix auquel la fenêtre se réinitialise.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/analytics/": {
      "get": {
        "summary": "Obtenir les analyses de l'application",
        "description": "Consultez les chiffres sous-jacents au [tableau de bord analytique](https://docs.didit.me/fr/console/analytics) de la Business Console pour une plage de dates. Sans `scope` ni `widget_keys`, la réponse correspond au résumé de la vérification des utilisateurs (KYC) (`ApplicationAnalyticsSummary`) : volumes quotidiens de sessions, totaux par statut, taux de conversion, mêmes chiffres pour la période précédente de même durée, localisations, données démographiques, appareils, entonnoirs de workflow, durée active de vérification, resoumissions, avertissements et séries temporelles. Avec `scope` ou `widget_keys`, il s'agit des widgets d'un onglet du tableau de bord (`ApplicationAnalyticsWidgetResponse`) : `kyc`, `kyb`, `transactions` ou `home`.\n\nLes décomptes de sessions sont calculés par date de création de session (UTC) et reflètent le statut actuel de chaque session. Ils proviennent d'agrégations quotidiennes actualisées en arrière-plan, de sorte que l'activité la plus récente peut mettre un court instant à apparaître. Les versions et identifiants de workflow invalides sont ignorés plutôt que rejetés. Rien n'est facturé.\n\nSeule une clé API à accès complet peut appeler cet endpoint : toute clé restreinte reçoit un code `403`, quels que soient ses accès, tout comme la clé d'une autre application. Consultez [API keys](https://docs.didit.me/fr/console/api-keys).",
        "operationId": "get_application_analytics",
        "x-didit-sdk": {
          "resource": "analytics",
          "method": "retrieve",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Analytics"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation.",
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application. Doit être l'application à laquelle appartient la clé API : une clé utilisée sur toute autre application reçoit une erreur `403`.",
            "example": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
          },
          {
            "name": "start_date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-01"
            },
            "description": "Premier jour de la plage, `YYYY-MM-DD`, inclus (UTC). À envoyer avec `end_date` : si l'un des deux est manquant, les deux sont ignorés et la plage s'étend de 30 jours avant aujourd'hui jusqu'à aujourd'hui."
          },
          {
            "name": "end_date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-15"
            },
            "description": "Dernier jour de la plage, `YYYY-MM-DD`, inclus (UTC). Une date future équivaut à aujourd'hui. La plage ne peut pas dépasser 730 jours."
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "home",
                "kyc",
                "kyb",
                "transactions"
              ]
            },
            "description": "Onglet du tableau de bord pour lequel renvoyer les widgets (insensible à la casse). Omettez-le, ainsi que `widget_keys`, pour obtenir le récapitulatif KYC. Envoyer uniquement `widget_keys` implique `kyc`. `home` accepte tout widget KYC, KYB ou de transaction et utilise par défaut la disposition d'accueil enregistrée de l'application."
          },
          {
            "name": "widget_keys",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "tx_count_total,tx_count_daily"
            },
            "description": "Clés de widgets séparées par des virgules, renvoyées dans cet ordre. Les clés non acceptées par le périmètre sont ignorées ; s'il n'en reste aucune, vous obtenez les valeurs par défaut du périmètre. KYC : `kyc_sessions_volume`, `kyc_warning_insights`, `kyc_id_locations`, `kyc_ip_locations`, `kyc_workflow_funnel`, `kyc_average_verification_time`, `kyc_conversion_rate`, `kyc_conversion_by_country`, `kyc_resubmission_insights`, `kyc_original_status_distribution`, `kyc_database_validation_coverage`, `kyc_database_validation_latency`, `kyc_demographics`, `kyc_device_details`. KYB : `kyb_sessions_volume`, `kyb_workflow_funnel`, `kyb_average_verification_time`, `kyb_ip_locations`, `kyb_business_country_distribution`, `kyb_warning_insights`, `kyb_conversion_rate`, `kyb_conversion_by_country`, `kyb_industry_breakdown`, `kyb_resubmission_insights`, `kyb_original_status_distribution`, `kyb_registry_coverage`, `kyb_registry_data_completeness`, `kyb_device_details`. Transactions : `tx_count_total`, `tx_count_daily`, `tx_volume_total_preferred_currency`, `tx_volume_daily_preferred_currency`, `tx_average_amount`, `tx_average_amount_daily`, `tx_transaction_category_breakdown`, `tx_action_type_breakdown`, `tx_status_volume_trend`, `tx_user_ip_or_country_distribution`, `tx_tag_breakdown`, `tx_top_rules_triggered`, `tx_team_member_performance`, `tx_score_histogram`."
          },
          {
            "name": "workflow_ids",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "33333333-4444-5555-6666-777777777777"
            },
            "description": "Identifiants de workflow séparés par des virgules. Limite le récapitulatif KYC ainsi que les widgets KYC et KYB à ces workflows. Les valeurs qui ne sont pas des UUID sont ignorées ; si aucune n'est valide, le filtre est abandonné. Le récapitulatif accepte également `workflow_id`."
          },
          {
            "name": "versions",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "3,4"
            },
            "description": "Numéros de version de workflow séparés par des virgules. S'applique uniquement en combinaison avec `workflow_ids` ; les valeurs qui ne sont pas des nombres entiers sont ignorées. `version` est accepté comme alias."
          },
          {
            "name": "branch_path_ids",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "default"
            },
            "description": "Identifiants de chemins de branche séparés par des virgules. S'applique uniquement avec `workflow_ids`, et seulement aux chiffres KYC. Les chiffres sont actuellement enregistrés uniquement pour `default` (tous les chemins combinés), toute autre valeur renvoie donc des chiffres vides. `branch_path_id` est accepté en alias."
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Widgets de transactions uniquement : UUID ou noms de tags séparés par des virgules."
          },
          {
            "name": "transaction_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "finance"
            },
            "description": "Widgets de transactions uniquement : catégories de transaction séparées par des virgules."
          },
          {
            "name": "action_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "withdrawal"
            },
            "description": "Widgets de transactions uniquement : types d'actions séparés par des virgules (insensible à la casse)."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/analytics/?start_date=2026-10-01&end_date=2026-10-15' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.analytics.retrieve()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.analytics.retrieve();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Analytics.Retrieve(ctx, didit.AnalyticsRetrieveParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.analytics().retrieve();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->analytics->retrieve();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.analytics.retrieve\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Analytics.RetrieveAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le récapitulatif KYC, ou les widgets demandés lorsque `scope` ou `widget_keys` est envoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ApplicationAnalyticsSummary"
                    },
                    {
                      "$ref": "#/components/schemas/ApplicationAnalyticsWidgetResponse"
                    }
                  ]
                },
                "examples": {
                  "KYC summary": {
                    "value": {
                      "grouping_mode": "day",
                      "data_points": [
                        {
                          "rounded_date": "2026-10-14",
                          "total": 12,
                          "approved": 8,
                          "declined": 1,
                          "canceled": 1,
                          "pending": 2,
                          "in_review": 1,
                          "expired": 1,
                          "abandoned": 0,
                          "in_progress": 1,
                          "not_started": 0,
                          "manually_approved": 1,
                          "manually_declined": 0
                        },
                        {
                          "rounded_date": "2026-10-15",
                          "total": 10,
                          "approved": 6,
                          "declined": 2,
                          "canceled": 0,
                          "pending": 2,
                          "in_review": 2,
                          "expired": 0,
                          "abandoned": 0,
                          "in_progress": 0,
                          "not_started": 0,
                          "manually_approved": 0,
                          "manually_declined": 1
                        }
                      ],
                      "request_breakdown": {
                        "total_approved": 14,
                        "total_in_review": 3,
                        "total_declined": 3,
                        "total_canceled": 1,
                        "total_pending": 4,
                        "total_expired": 1,
                        "total_abandoned": 0,
                        "total_in_progress": 1,
                        "total_not_started": 0,
                        "total_manually_approved": 1,
                        "total_manually_declined": 1
                      },
                      "conversion_rate": 70.0,
                      "location_stats": {
                        "countries": [
                          {
                            "session_count": 15,
                            "country": "Spain",
                            "country_code": "ES"
                          },
                          {
                            "session_count": 7,
                            "country": "Portugal",
                            "country_code": "PT"
                          }
                        ],
                        "ip_countries": [
                          {
                            "session_count": 15,
                            "country": "Spain",
                            "country_code": "ES"
                          },
                          {
                            "session_count": 7,
                            "country": "Portugal",
                            "country_code": "PT"
                          }
                        ],
                        "id_countries": [
                          {
                            "country": "Spain",
                            "country_code": "ES",
                            "session_count": 14
                          },
                          {
                            "country": "Portugal",
                            "country_code": "PT",
                            "session_count": 6
                          }
                        ],
                        "conversion_by_country": [
                          {
                            "country": "Spain",
                            "country_code": "ES",
                            "finished": 13,
                            "approved": 10
                          },
                          {
                            "country": "Portugal",
                            "country_code": "PT",
                            "finished": 6,
                            "approved": 4
                          }
                        ],
                        "cities": [
                          {
                            "session_count": 9,
                            "location": "Madrid, Spain",
                            "latitude": 40.4168,
                            "longitude": -3.7038
                          }
                        ]
                      },
                      "demographic_stats": {
                        "age_distribution": {
                          "under_18": 0,
                          "18_24": 5,
                          "25_34": 8,
                          "35_44": 4,
                          "45_64": 2,
                          "65_plus": 1
                        },
                        "gender_distribution": {
                          "M": 11,
                          "F": 9
                        }
                      },
                      "device_details": {
                        "device_models": [
                          {
                            "device": "Apple",
                            "count": 12
                          },
                          {
                            "device": "Android",
                            "count": 10
                          }
                        ],
                        "browsers": [
                          {
                            "browser": "Safari",
                            "count": 12
                          },
                          {
                            "browser": "Chrome",
                            "count": 10
                          }
                        ],
                        "operating_systems": [
                          {
                            "os": "iOS",
                            "count": 12
                          },
                          {
                            "os": "Android",
                            "count": 10
                          }
                        ]
                      },
                      "workflow_funnel_stats": {
                        "33333333-4444-5555-6666-777777777777": {
                          "total": 22,
                          "steps": {
                            "OCR": {
                              "reached": 21
                            },
                            "LIVENESS": {
                              "reached": 19
                            },
                            "FACE_MATCH": {
                              "reached": 19
                            },
                            "AML": {
                              "reached": 18
                            }
                          }
                        }
                      },
                      "verification_time_stats": {
                        "overall_avg_seconds": 64.0,
                        "overall_count": 18,
                        "per_feature": {
                          "OCR": {
                            "avg_seconds": 41.2,
                            "total_seconds": 741.6,
                            "count": 18
                          },
                          "LIVENESS": {
                            "avg_seconds": 22.8,
                            "total_seconds": 410.4,
                            "count": 18
                          }
                        },
                        "per_sub_step": {
                          "OCR": {
                            "front_id_photo": {
                              "avg_seconds": 18.3,
                              "total_seconds": 329.4,
                              "count": 18
                            }
                          }
                        }
                      },
                      "resubmission_stats": {
                        "first_pass": 17,
                        "second": 2,
                        "third_plus": 1,
                        "abandoned": 0
                      },
                      "warning_stats": {
                        "ID_VERIFICATION": {
                          "total": 21,
                          "risks": {
                            "DOCUMENT_EXPIRED": {
                              "error": 1,
                              "warning": 0,
                              "information": 0
                            }
                          }
                        },
                        "LIVENESS": {
                          "total": 19,
                          "risks": {
                            "LOW_LIVENESS_SCORE": {
                              "error": 0,
                              "warning": 2,
                              "information": 0
                            }
                          }
                        }
                      },
                      "original_status_stats": {
                        "approved": 13,
                        "in_review": 5,
                        "declined": 2
                      },
                      "demographic_time_series": [
                        {
                          "date": "2026-10-14",
                          "age_distribution": {
                            "under_18": 0,
                            "18_24": 3,
                            "25_34": 4,
                            "35_44": 2,
                            "45_64": 1,
                            "65_plus": 0
                          },
                          "gender_distribution": {
                            "M": 6,
                            "F": 4
                          }
                        },
                        {
                          "date": "2026-10-15",
                          "age_distribution": {
                            "under_18": 0,
                            "18_24": 2,
                            "25_34": 4,
                            "35_44": 2,
                            "45_64": 1,
                            "65_plus": 1
                          },
                          "gender_distribution": {
                            "M": 5,
                            "F": 5
                          }
                        }
                      ],
                      "device_time_series": [
                        {
                          "date": "2026-10-14",
                          "devices": {
                            "Apple": 7,
                            "Android": 5
                          },
                          "browsers": {
                            "Safari": 7,
                            "Chrome": 5
                          },
                          "operating_systems": {
                            "iOS": 7,
                            "Android": 5
                          }
                        },
                        {
                          "date": "2026-10-15",
                          "devices": {
                            "Apple": 5,
                            "Android": 5
                          },
                          "browsers": {
                            "Safari": 5,
                            "Chrome": 5
                          },
                          "operating_systems": {
                            "iOS": 5,
                            "Android": 5
                          }
                        }
                      ],
                      "verification_time_time_series": [
                        {
                          "date": "2026-10-14",
                          "overall_avg": 66.1,
                          "per_feature": {
                            "OCR": 42.0,
                            "LIVENESS": 24.1
                          }
                        },
                        {
                          "date": "2026-10-15",
                          "overall_avg": 61.5,
                          "per_feature": {
                            "OCR": 40.2,
                            "LIVENESS": 21.3
                          }
                        }
                      ],
                      "resubmission_time_series": [
                        {
                          "date": "2026-10-14",
                          "first_pass": 9,
                          "second": 1,
                          "third_plus": 0,
                          "abandoned": 0
                        },
                        {
                          "date": "2026-10-15",
                          "first_pass": 8,
                          "second": 1,
                          "third_plus": 1,
                          "abandoned": 0
                        }
                      ],
                      "original_status_time_series": [
                        {
                          "date": "2026-10-14",
                          "approved": 7,
                          "in_review": 3,
                          "declined": 1
                        },
                        {
                          "date": "2026-10-15",
                          "approved": 6,
                          "in_review": 2,
                          "declined": 1
                        }
                      ],
                      "previous_data_points": [
                        {
                          "rounded_date": "2026-10-12",
                          "total": 9,
                          "approved": 6,
                          "declined": 1,
                          "canceled": 1,
                          "pending": 1
                        },
                        {
                          "rounded_date": "2026-10-13",
                          "total": 11,
                          "approved": 7,
                          "declined": 2,
                          "canceled": 0,
                          "pending": 2
                        }
                      ],
                      "previous_request_breakdown": {
                        "total_approved": 13,
                        "total_in_review": 2,
                        "total_declined": 3,
                        "total_canceled": 1,
                        "total_pending": 3
                      }
                    }
                  },
                  "Transaction widgets": {
                    "value": {
                      "scope": "transactions",
                      "available_widget_keys": [
                        "tx_count_total",
                        "tx_count_daily",
                        "tx_volume_total_preferred_currency",
                        "tx_volume_daily_preferred_currency",
                        "tx_average_amount",
                        "tx_average_amount_daily",
                        "tx_transaction_category_breakdown",
                        "tx_action_type_breakdown",
                        "tx_status_volume_trend",
                        "tx_user_ip_or_country_distribution",
                        "tx_tag_breakdown",
                        "tx_top_rules_triggered",
                        "tx_team_member_performance",
                        "tx_score_histogram"
                      ],
                      "requested_widget_keys": [
                        "tx_count_total",
                        "tx_count_daily"
                      ],
                      "widgets": {
                        "tx_count_total": {
                          "kind": "metric",
                          "title": "Transaction count",
                          "value": 42
                        },
                        "tx_count_daily": {
                          "kind": "time_series",
                          "title": "Transaction count",
                          "items": [
                            {
                              "date": "2026-10-14",
                              "value": 20
                            },
                            {
                              "date": "2026-10-15",
                              "value": 22
                            }
                          ],
                          "previous_items": [
                            {
                              "date": "2026-10-12",
                              "value": 18
                            },
                            {
                              "date": "2026-10-13",
                              "value": 15
                            }
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Plage de dates ou portée non valide. Le corps est un objet indexé par le paramètre en cause, avec un message sous forme de chaîne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  }
                },
                "examples": {
                  "Bad date format": {
                    "value": {
                      "start_date": "Invalid date format. Use YYYY-MM-DD (e.g., 2024-01-15)."
                    }
                  },
                  "Start after end": {
                    "value": {
                      "start_date": "Start date must be before or equal to end date."
                    }
                  },
                  "Range too long": {
                    "value": {
                      "date_range": "Date range cannot exceed 730 days (2 years)."
                    }
                  },
                  "Unknown scope": {
                    "value": {
                      "scope": "Unsupported analytics scope."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré. Seule une clé créée avec une date d'expiration peut expirer ; après cette date, chaque requête effectuée avec celle-ci renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Consultez `detail` : une clé API manquante (une clé erronée, révoquée ou expirée renvoie `401`), une clé d'une autre application, toute clé avec restriction de portée, ou une requête provenant de l'extérieur de la liste d'adresses IP de la clé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Another application": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key": {
                    "value": {
                      "detail": "This API key has no access to this endpoint."
                    }
                  },
                  "Outside the key's IP list": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 600 requêtes GET par minute avec cette clé API. Attendez le nombre de secondes indiqué dans `Retry-After`, puis réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes avant la réinitialisation de la fenêtre actuelle d'une minute.",
                "schema": {
                  "type": "integer",
                  "example": 23
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées par minute dans ce budget.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix auquel la fenêtre se réinitialise.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/analytics/today/": {
      "get": {
        "summary": "Obtenir les vérifications du jour par heure",
        "operationId": "get_application_analytics_today",
        "x-didit-sdk": {
          "resource": "analytics",
          "method": "retrieve_today",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Analytics"
        ],
        "description": "Sessions de vérification des utilisateurs (KYC) d'aujourd'hui, à partir de minuit heure locale dans `tz`, comptabilisées par heure locale de création, aux côtés des mêmes heures du même jour de la semaine une semaine auparavant, et réparties selon le résultat actuel : approuvé, en cours d'examen ou refusé. Il s'agit de la carte de volume de l'écran d'accueil de la Business Console.\n\n`total` correspond à aujourd'hui jusqu'à présent. `previous_total_so_far` comptabilise le jour de comparaison uniquement jusqu'à la même heure locale, de sorte qu'une variation entre les deux compare la même partie des deux journées. Les heures restant à venir aujourd'hui valent `0`. Un jour de changement d'heure compte 23 ou 25 heures : l'heure manquante reste à `0` et l'heure répétée cumule les deux.",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation.",
            "example": "11111111-2222-3333-4444-555555555555"
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application. Doit être l'application à laquelle appartient la clé API : une clé utilisée sur toute autre application reçoit une erreur `403`.",
            "example": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "UTC",
              "example": "Europe/Madrid"
            },
            "description": "Fuseau horaire IANA dont minuit marque le début d'aujourd'hui, par exemple `Europe/Madrid` ou `America/Mexico_City`. Omettez-le pour UTC."
          }
        ],
        "responses": {
          "200": {
            "description": "Vérifications d'aujourd'hui par heure locale, celles du jour de comparaison et les résultats d'aujourd'hui.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationAnalyticsToday"
                },
                "examples": {
                  "Madrid, 14:00": {
                    "value": {
                      "time_zone": "Europe/Madrid",
                      "date": "2026-10-30",
                      "current_hour": 14,
                      "previous_date": "2026-10-23",
                      "hours": [
                        3,
                        1,
                        0,
                        0,
                        1,
                        2,
                        4,
                        9,
                        14,
                        18,
                        21,
                        19,
                        22,
                        24,
                        27,
                        0,
                        0,
                        0,
                        0,
                        0,
                        0,
                        0,
                        0,
                        0
                      ],
                      "previous_hours": [
                        2,
                        1,
                        1,
                        0,
                        1,
                        3,
                        5,
                        8,
                        12,
                        16,
                        19,
                        18,
                        20,
                        22,
                        24,
                        26,
                        23,
                        19,
                        15,
                        12,
                        9,
                        7,
                        5,
                        3
                      ],
                      "total": 165,
                      "previous_total_so_far": 151,
                      "outcomes": {
                        "approved": 139,
                        "in_review": 6,
                        "declined": 18
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Fuseau horaire inconnu. Le corps est indexé par le paramètre, avec une liste de messages.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Unknown time zone": {
                    "value": {
                      "tz": [
                        "Unknown time zone: Europe/Atlantis."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré. Seule une clé créée avec une date d'expiration peut expirer ; après cette date, chaque requête effectuée avec celle-ci renvoie `401`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. Consultez `detail` : une clé API manquante ou invalide (jamais `401`), une clé d'une autre application, toute clé avec restriction de portée, ou une requête provenant de l'extérieur de la liste d'adresses IP de la clé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Another application": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key": {
                    "value": {
                      "detail": "This API key has no access to this endpoint."
                    }
                  },
                  "Outside the key's IP list": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 600 requêtes GET par minute avec cette clé API. Attendez le nombre de secondes indiqué dans `Retry-After`, puis réessayez.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes avant la réinitialisation de la fenêtre actuelle d'une minute.",
                "schema": {
                  "type": "integer",
                  "example": 23
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées par minute dans ce budget.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix auquel la fenêtre se réinitialise.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/analytics/today/?tz=Europe%2FMadrid' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/webhooks/": {
      "get": {
        "summary": "Lister les livraisons de webhook de session",
        "description": "Lister chaque livraison de webhook enregistrée par Didit pour une session de vérification d'utilisateur (KYC) ou d'entreprise (KYB), de la plus récente à la plus ancienne, sous la forme d'un tableau JSON brut (non paginé). Chaque entrée correspond à une tentative vers une destination : le premier envoi, chaque [nouvelle tentative](https://docs.didit.me/fr/integration/webhooks#politique-de-nouvelles-tentatives) automatique et chaque renvoi sont des entrées distinctes avec leur propre `uuid`, et les nouvelles tentatives ainsi que les renvois conservent l'`event_id` du payload. `request_header` et `request_body` sont du texte JSON ; analysez-les pour lire les signatures et le payload. Les enregistrements de livraison sont disponibles pendant environ 30 jours, un tableau vide signifie donc qu'aucun webhook n'a encore été envoyé pour la session ou que toutes les livraisons sont plus anciennes que ce délai. Une clé API restreinte nécessite `sessions: read` et `decisions: read`.",
        "operationId": "get_v3_session_webhooks",
        "x-didit-sdk": {
          "resource": "sessions.webhooks",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification, utilisateur (KYC) ou entreprise (KYB) : le `session_id` renvoyé par `POST /v3/session/`. Le serveur le résout pour les deux types de session.\n\n**Doit être un UUID valide.** La route ne correspond qu'aux UUID bien formés ; une valeur malformée est donc rejetée par le routeur d'URL avant l'exécution de tout code d'application et la réponse est une page **HTML** `404` plutôt que l'enveloppe JSON `{\"detail\": ...}` illustrée ci-dessous.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "22222222-3333-4444-5555-666666666666"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/session/22222222-3333-4444-5555-666666666666/webhooks/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.webhooks.list(\n    \"22222222-3333-4444-5555-666666666666\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.webhooks.list(\"22222222-3333-4444-5555-666666666666\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Webhooks.List(ctx, \"22222222-3333-4444-5555-666666666666\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().webhooks().list(\"22222222-3333-4444-5555-666666666666\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->webhooks->list('22222222-3333-4444-5555-666666666666');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.sessions.webhooks.list(\"22222222-3333-4444-5555-666666666666\").each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Webhooks.ListAsync(\"22222222-3333-4444-5555-666666666666\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Chaque livraison enregistrée pour la session, de la plus récente à la plus ancienne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SessionWebhookDelivery"
                  }
                },
                "examples": {
                  "Failed delivery and its successful retry": {
                    "value": [
                      {
                        "uuid": "66666666-7777-8888-9999-000000000002",
                        "session_id": "22222222-3333-4444-5555-666666666666",
                        "request_url": "https://yourapp.com/webhooks/didit",
                        "response_status": 200,
                        "status": "In Progress",
                        "webhook_type": "status.updated",
                        "request_header": "{\"Content-Type\": \"application/json\", \"X-Signature\": \"9188851d160b5b3aacfc946e4dde1f061b7e568662518942c927ddaf507f533d\", \"X-Signature-V2\": \"381236af514d3fb538579365ac5a24f2464ce1b8224c6e770c60d8201c43ecc5\", \"X-Signature-Simple\": \"4740131dc38f29e78a8508371979be74967d5307464494bd3148a03b4d6c8716\", \"X-Timestamp\": \"1792056139\", \"User-Agent\": \"DiditWebhook/2.0 +https://didit.me\"}",
                        "request_body": "{\"application_id\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"created_at\":1792056057,\"environment\":\"live\",\"event_id\":\"33333333-4444-5555-6666-777777777777\",\"sandbox_scenario\":null,\"session_id\":\"22222222-3333-4444-5555-666666666666\",\"status\":\"In Progress\",\"timestamp\":1792056139,\"vendor_data\":\"user-123\",\"webhook_type\":\"status.updated\",\"workflow_id\":\"44444444-5555-6666-7777-888888888888\",\"workflow_version\":3}",
                        "created_at": "2026-10-15T09:22:19.104233Z"
                      },
                      {
                        "uuid": "66666666-7777-8888-9999-000000000001",
                        "session_id": "22222222-3333-4444-5555-666666666666",
                        "request_url": "https://yourapp.com/webhooks/didit",
                        "response_status": 503,
                        "status": "In Progress",
                        "webhook_type": "status.updated",
                        "request_header": "{\"Content-Type\": \"application/json\", \"X-Signature\": \"a5e02a03404e1337a0198e6be15d34abbd053c658a0e51e5d0e78554213ef29b\", \"X-Signature-V2\": \"927e7cb770c94ce745939bff73f04aa200015f3bc64795ba46c2aaf78a6cedc5\", \"X-Signature-Simple\": \"e37b0d4c716c72bb5ae7127b9cc455d28ab4686e9e22312b4ec2327409a73302\", \"X-Timestamp\": \"1792056078\", \"User-Agent\": \"DiditWebhook/2.0 +https://didit.me\"}",
                        "request_body": "{\"application_id\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"created_at\":1792056057,\"environment\":\"live\",\"event_id\":\"33333333-4444-5555-6666-777777777777\",\"sandbox_scenario\":null,\"session_id\":\"22222222-3333-4444-5555-666666666666\",\"status\":\"In Progress\",\"timestamp\":1792056078,\"vendor_data\":\"user-123\",\"webhook_type\":\"status.updated\",\"workflow_id\":\"44444444-5555-6666-7777-888888888888\",\"workflow_version\":3}",
                        "created_at": "2026-10-15T09:21:18.412345Z"
                      }
                    ]
                  },
                  "No webhook sent yet": {
                    "value": []
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. L'absence de `x-api-key`, ou une clé invalide ou révoquée, renvoie `Authentication credentials were not provided or are invalid.` Une clé appartenant à une autre application renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.` Un `sessionId` inconnu renvoie `404` avant la vérification des identifiants.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Key of another application": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without sessions read": {
                    "value": {
                      "detail": "This API key has no read access to sessions."
                    }
                  },
                  "Scoped key without decisions read": {
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas ou a été supprimée (`Not found.`, renvoyé avant la vérification des identifiants), ou elle se trouve en dehors des limites de workflow ou de statut d'une clé restreinte (`Session not found.`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside the key's limits": {
                    "value": {
                      "detail": "Session not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 600 requêtes GET dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (600).",
                "schema": {
                  "type": "integer",
                  "example": 600
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-get"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/webhook/{webhook_uuid}": {
      "get": {
        "summary": "Obtenir la livraison du webhook de session",
        "description": "Récupérer une livraison de webhook d'une session de vérification : l'URL vers laquelle elle a été envoyée, le statut HTTP renvoyé par votre endpoint, ainsi que les en-têtes et le corps JSON exacts envoyés par Didit. `request_header` et `request_body` sont du texte JSON ; pour vérifier votre [vérification de signature](https://docs.didit.me/fr/integration/webhooks#vérification-de-la-signature), recalculez `X-Signature-V2` à partir du corps analysé avec le secret de la destination à laquelle elle a été envoyée (ou le secret au niveau de l'application pour une livraison vers l'URL de webhook héritée). Le chemin ne comporte pas de barre oblique finale : avec une, il renvoie `404`. Une clé API avec restriction de portée nécessite `sessions: read` et `decisions: read`.",
        "operationId": "get_v3_session_webhook",
        "x-didit-sdk": {
          "resource": "sessions.webhooks",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification, utilisateur (KYC) ou entreprise (KYB) : le `session_id` renvoyé par `POST /v3/session/`. Le serveur le résout pour les deux types de session.\n\n**Doit être un UUID valide.** La route ne correspond qu'aux UUID bien formés ; une valeur malformée est donc rejetée par le routeur d'URL avant l'exécution de tout code d'application et la réponse est une page **HTML** `404` plutôt que l'enveloppe JSON `{\"detail\": ...}` illustrée ci-dessous.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "22222222-3333-4444-5555-666666666666"
          },
          {
            "name": "webhook_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la livraison : le `uuid` d'une entrée renvoyée par `GET /v3/session/{sessionId}/webhooks/`. Il doit appartenir à la session présente dans le chemin.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "66666666-7777-8888-9999-000000000001"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/session/22222222-3333-4444-5555-666666666666/webhook/66666666-7777-8888-9999-000000000001' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.webhooks.retrieve(\n    \"22222222-3333-4444-5555-666666666666\",\n    \"66666666-7777-8888-9999-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.webhooks.retrieve(\n  \"22222222-3333-4444-5555-666666666666\",\n  \"66666666-7777-8888-9999-000000000001\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Webhooks.Retrieve(ctx, \"22222222-3333-4444-5555-666666666666\", \"66666666-7777-8888-9999-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().webhooks().retrieve(\"22222222-3333-4444-5555-666666666666\", \"66666666-7777-8888-9999-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->webhooks->retrieve('22222222-3333-4444-5555-666666666666', '66666666-7777-8888-9999-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.webhooks.retrieve(\n  \"22222222-3333-4444-5555-666666666666\",\n  \"66666666-7777-8888-9999-000000000001\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Webhooks.RetrieveAsync(\"22222222-3333-4444-5555-666666666666\", \"66666666-7777-8888-9999-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La livraison, avec ses en-têtes et son corps de requête.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionWebhookDelivery"
                },
                "examples": {
                  "Connection failure": {
                    "value": {
                      "uuid": "66666666-7777-8888-9999-000000000001",
                      "session_id": "22222222-3333-4444-5555-666666666666",
                      "request_url": "https://yourapp.com/webhooks/didit",
                      "response_status": 503,
                      "status": "In Progress",
                      "webhook_type": "status.updated",
                      "request_header": "{\"Content-Type\": \"application/json\", \"X-Signature\": \"a5e02a03404e1337a0198e6be15d34abbd053c658a0e51e5d0e78554213ef29b\", \"X-Signature-V2\": \"927e7cb770c94ce745939bff73f04aa200015f3bc64795ba46c2aaf78a6cedc5\", \"X-Signature-Simple\": \"e37b0d4c716c72bb5ae7127b9cc455d28ab4686e9e22312b4ec2327409a73302\", \"X-Timestamp\": \"1792056078\", \"User-Agent\": \"DiditWebhook/2.0 +https://didit.me\"}",
                      "request_body": "{\"application_id\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"created_at\":1792056057,\"environment\":\"live\",\"event_id\":\"33333333-4444-5555-6666-777777777777\",\"sandbox_scenario\":null,\"session_id\":\"22222222-3333-4444-5555-666666666666\",\"status\":\"In Progress\",\"timestamp\":1792056078,\"vendor_data\":\"user-123\",\"webhook_type\":\"status.updated\",\"workflow_id\":\"44444444-5555-6666-7777-888888888888\",\"workflow_version\":3}",
                      "created_at": "2026-10-15T09:21:18.412345Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. L'absence de `x-api-key`, ou une clé invalide ou révoquée, renvoie `Authentication credentials were not provided or are invalid.` Une clé appartenant à une autre application renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.` Un `sessionId` inconnu renvoie `404` avant la vérification des identifiants.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Key of another application": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without sessions read": {
                    "value": {
                      "detail": "This API key has no read access to sessions."
                    }
                  },
                  "Scoped key without decisions read": {
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas ou a été supprimée (`Not found.`, renvoyé avant la vérification des identifiants), ou elle se trouve en dehors des limites de workflow ou de statut d'une clé restreinte (`Session not found.`). Une livraison qui n'existe pas, appartient à une autre session ou n'est plus disponible renvoie `No WebhookLog matches the given query.`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside the key's limits": {
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "Delivery not in this session": {
                    "value": {
                      "detail": "No WebhookLog matches the given query."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 600 requêtes GET dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (600).",
                "schema": {
                  "type": "integer",
                  "example": 600
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-get"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/webhook/{webhook_uuid}/resend": {
      "post": {
        "summary": "Renvoyer la livraison du webhook de session",
        "description": "Renvoyez un webhook de session enregistré vers l'URL à laquelle il a été envoyé initialement, avec le même payload et le même `event_id`, ainsi qu'un `timestamp`, un en-tête `X-Timestamp` et des signatures actualisés. Didit le signe avec le secret actuel de la destination à laquelle appartient la livraison (ou le secret au niveau de l'application pour une livraison vers l'URL de webhook historique), attend jusqu'à 5 secondes la réponse de votre endpoint, enregistre la tentative en tant que nouvelle livraison et la renvoie avec un code `200`, quelle que soit la réponse de votre endpoint : consultez `response_status`. Un renvoi n'est pas réessayé automatiquement, et chaque appel effectue un nouvel envoi ; rendez donc votre endpoint idempotent sur l'`event_id`. Le chemin ne comporte pas de barre oblique finale et la requête n'a pas de corps. Une clé API restreinte nécessite `webhooks: write` et `decisions: read`.",
        "operationId": "post_v3_session_webhook_resend",
        "x-didit-sdk": {
          "resource": "sessions.webhooks",
          "method": "resend",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification, utilisateur (KYC) ou entreprise (KYB) : le `session_id` renvoyé par `POST /v3/session/`. Le serveur le résout pour les deux types de session.\n\n**Doit être un UUID valide.** La route ne correspond qu'aux UUID bien formés ; une valeur malformée est donc rejetée par le routeur d'URL avant l'exécution de tout code d'application et la réponse est une page **HTML** `404` plutôt que l'enveloppe JSON `{\"detail\": ...}` illustrée ci-dessous.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "22222222-3333-4444-5555-666666666666"
          },
          {
            "name": "webhook_uuid",
            "in": "path",
            "required": true,
            "description": "UUID de la livraison à renvoyer : le `uuid` d'une entrée renvoyée par `GET /v3/session/{sessionId}/webhooks/`. Il doit appartenir à la session présente dans le chemin.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "66666666-7777-8888-9999-000000000001"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/session/22222222-3333-4444-5555-666666666666/webhook/66666666-7777-8888-9999-000000000001/resend' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.webhooks.resend(\n    \"22222222-3333-4444-5555-666666666666\",\n    \"66666666-7777-8888-9999-000000000001\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.webhooks.resend(\n  \"22222222-3333-4444-5555-666666666666\",\n  \"66666666-7777-8888-9999-000000000001\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Webhooks.Resend(ctx, \"22222222-3333-4444-5555-666666666666\", \"66666666-7777-8888-9999-000000000001\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().webhooks().resend(\"22222222-3333-4444-5555-666666666666\", \"66666666-7777-8888-9999-000000000001\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->webhooks->resend('22222222-3333-4444-5555-666666666666', '66666666-7777-8888-9999-000000000001');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.webhooks.resend(\n  \"22222222-3333-4444-5555-666666666666\",\n  \"66666666-7777-8888-9999-000000000001\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Webhooks.ResendAsync(\"22222222-3333-4444-5555-666666666666\", \"66666666-7777-8888-9999-000000000001\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "La nouvelle livraison, déjà tentée. `response_status` est la réponse de votre endpoint cette fois-ci. La livraison d'origine reste inchangée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionWebhookDelivery"
                },
                "examples": {
                  "Accepted on resend": {
                    "value": {
                      "uuid": "66666666-7777-8888-9999-000000000004",
                      "session_id": "22222222-3333-4444-5555-666666666666",
                      "request_url": "https://yourapp.com/webhooks/didit",
                      "response_status": 200,
                      "status": "In Progress",
                      "webhook_type": "status.updated",
                      "request_header": "{\"Content-Type\": \"application/json\", \"X-Signature\": \"b8eb1e376517ee0cad8ba98ff7f8fd35fc72eca231000963a96a335f82328835\", \"X-Signature-V2\": \"9efd2ce9ed1303e1d05273ef9608a59363ed9789a05253db4748b3e8e50cb109\", \"X-Signature-Simple\": \"bf3a9dc04b2c20ab539203b0cd5cca2a10f630bf62d8feb6d68d82af80f64774\", \"X-Timestamp\": \"1792159542\", \"User-Agent\": \"DiditWebhook/2.0 +https://didit.me\"}",
                      "request_body": "{\"application_id\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"created_at\":1792056057,\"environment\":\"live\",\"event_id\":\"33333333-4444-5555-6666-777777777777\",\"sandbox_scenario\":null,\"session_id\":\"22222222-3333-4444-5555-666666666666\",\"status\":\"In Progress\",\"timestamp\":1792159542,\"vendor_data\":\"user-123\",\"webhook_type\":\"status.updated\",\"workflow_id\":\"44444444-5555-6666-7777-888888888888\",\"workflow_version\":3}",
                      "created_at": "2026-10-16T14:05:42.330981Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "La livraison n'a pas pu être renvoyée. Basez-vous sur `code` : `webhook_url_missing` signifie que la livraison n'a pas d'URL enregistrée et rien n'est envoyé ; `webhook_resend_error` signifie que la livraison stockée n'a pas pu être signée à nouveau ou que la tentative n'a pas pu être effectuée. Après `webhook_resend_error`, `detail` commence par `Error processing webhook resend:` suivi d'un texte de diagnostic susceptible de changer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    },
                    "code": {
                      "type": "string",
                      "description": "Code d'erreur stable lisible par machine. Effectuez vos branchements sur cette valeur, pas sur `detail`."
                    }
                  }
                },
                "examples": {
                  "No recorded URL": {
                    "value": {
                      "detail": "The webhook delivery does not have a request URL configured",
                      "code": "webhook_url_missing"
                    }
                  },
                  "Resend failed": {
                    "value": {
                      "detail": "Error processing webhook resend: Invalid webhook data format",
                      "code": "webhook_resend_error"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API a expiré : elle a été créée avec une date d'expiration qui est dépassée. Une clé incorrecte ou révoquée reçoit également un code `401` ; une clé manquante reçoit un code `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La requête n'est pas autorisée. L'absence de `x-api-key`, ou une clé invalide ou révoquée, renvoie `Authentication credentials were not provided or are invalid.` Une clé appartenant à une autre application renvoie `You do not have permission to perform this action.` Une clé avec restriction de portée sans l'accès requis par cet endpoint renvoie un message indiquant l'accès manquant, et une clé utilisée en dehors de sa liste d'autorisation d'adresses IP renvoie `This API key can't be used from this IP address.` Un `sessionId` inconnu renvoie `404` avant la vérification des identifiants.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid key": {
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Key of another application": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without webhooks write": {
                    "value": {
                      "detail": "This API key has no write access to webhooks."
                    }
                  },
                  "Scoped key without decisions read": {
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "Outside the IP allowlist": {
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas ou a été supprimée (`Not found.`, renvoyé avant la vérification des identifiants), ou elle se trouve en dehors des limites de workflow ou de statut d'une clé restreinte (`Session not found.`). Une livraison qui n'existe pas, appartient à une autre session ou n'est plus disponible renvoie `Webhook log not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside the key's limits": {
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "Delivery not in this session": {
                    "value": {
                      "detail": "Webhook log not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : plus de 300 requêtes d'écriture (POST, PATCH, PUT, DELETE) dans la fenêtre actuelle d'une minute pour cette clé API. Attendez `Retry-After` secondes avant de réessayer.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requêtes autorisées dans la fenêtre d'une minute (300).",
                "schema": {
                  "type": "integer",
                  "example": 300
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requêtes restantes dans la fenêtre actuelle.",
                "schema": {
                  "type": "integer",
                  "example": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "Temps Unix (en secondes) auquel la fenêtre actuelle se réinitialise.",
                "schema": {
                  "type": "integer",
                  "example": 1792056120
                }
              },
              "X-RateLimit-Scope": {
                "description": "Nom du budget qui a été dépassé.",
                "schema": {
                  "type": "string",
                  "example": "generic-write"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Throttled": {
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/events/": {
      "get": {
        "summary": "Lister les événements de session",
        "description": "Consultez la chronologie des événements d'une session de vérification, du plus récent au plus ancien selon `sent_at` : les écrans vus par l'utilisateur, les boutons et les téléversements, les tentatives échouées, les changements de statut et d'étapes de fonctionnalités, ainsi que la trace de routage du workflow. Fonctionne pour les identifiants de session de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB). Les événements étant stockés de manière asynchrone, un nouvel événement peut mettre quelques secondes à apparaître. Les résultats sont paginés avec `limit` et `offset` ; suivez `next` jusqu'à ce qu'il soit `null`. Une clé API restreinte nécessite `sessions: read` et `decisions: read`, et sans `media: read`, elle reçoit `file_url` avec la valeur `null`. Les événements de routage sont décrits dans [Retrieve session](https://docs.didit.me/fr/sessions-api/retrieve-session).",
        "operationId": "get_v3_session_events",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "list_events",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification (le `session_id` renvoyé par `POST /v3/session/`). Accepte les identifiants de session de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) : le serveur résout l'identifiant pour les deux types de session. Doit être un UUID bien formé ; une valeur malformée ne correspond pas à la route et renvoie une erreur HTML `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Nombre maximal d'événements par page. Vaut par défaut 50. Une valeur inférieure à 1 ou non numérique revient à 50 ; une valeur supérieure à 1,000,000 renvoie `400`.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000,
              "example": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Nombre de résultats à ignorer avant le premier renvoyé. La valeur par défaut est 0 ; une valeur négative ou non numérique revient à 0, une valeur supérieure à 1,000,000 renvoie `400`. Privilégiez l'utilisation des URL `next` et `previous`.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000,
              "example": 0
            }
          },
          {
            "name": "ordering",
            "in": "query",
            "required": false,
            "description": "Remplacement de tri optionnel. L'ordre par défaut est `-sent_at`. Transmettez le nom d'un champ de résultat (par exemple `sent_at`, `created_at`, `event_type`, `feature_step` ou `step`) pour un tri croissant, préfixez-le par `-` pour un tri décroissant, et séparez plusieurs champs par des virgules. Les champs inconnus sont ignorés.",
            "schema": {
              "type": "string",
              "example": "sent_at"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/events/?limit=50' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.sessions.list_events(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.sessions.listEvents(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Sessions.ListEventsAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsListEventsParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.sessions().listEvents(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->sessions->listEvents('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.sessions.list_events(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Sessions.ListEventsAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page d'événements de la session, du plus récent au plus ancien.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Nombre total d'événements de la session."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SessionEvent"
                      }
                    }
                  }
                },
                "examples": {
                  "Completed session": {
                    "value": {
                      "count": 3,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "aaaaaaaa-1111-2222-3333-444444444444",
                          "event_type": "SESSION_STATUS_CHANGED",
                          "created_at": "2026-09-14T10:02:13.904512Z",
                          "component": null,
                          "feature_step": null,
                          "step": null,
                          "details": {
                            "old_status": "In Progress",
                            "current_status": "Approved"
                          },
                          "ip_address": null,
                          "user_agent": null,
                          "device_info": null,
                          "file_url": null,
                          "sent_at": 1789380131482
                        },
                        {
                          "uuid": "bbbbbbbb-1111-2222-3333-444444444444",
                          "event_type": "FEATURE_STEP_CHANGED",
                          "created_at": "2026-09-14T10:01:49.210377Z",
                          "component": null,
                          "feature_step": null,
                          "step": null,
                          "details": {
                            "old_feature_step": "OCR",
                            "current_feature_step": "LIVENESS"
                          },
                          "ip_address": null,
                          "user_agent": null,
                          "device_info": null,
                          "file_url": null,
                          "sent_at": 1789380107103
                        },
                        {
                          "uuid": "cccccccc-1111-2222-3333-444444444444",
                          "event_type": "STEP_RENDERED",
                          "created_at": "2026-09-14T10:01:00.581930Z",
                          "component": "DocumentCapture",
                          "feature_step": "OCR",
                          "step": "DOCUMENT_CAPTURE_FRONT",
                          "details": {},
                          "ip_address": "203.0.113.24",
                          "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1",
                          "device_info": {
                            "device_model": "iPhone"
                          },
                          "file_url": null,
                          "sent_at": 1789380058776
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`limit` ou `offset` est supérieur à 1 000 000. Le corps est un tableau JSON contenant un seul message.",
            "content": {
              "application/json": {
                "examples": {
                  "Limit too large": {
                    "summary": "limit=2000000",
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  },
                  "Offset too large": {
                    "summary": "offset=2000000",
                    "value": [
                      "offset must not exceed 1000000."
                    ]
                  }
                },
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without sessions read": {
                    "summary": "La clé restreinte ne dispose pas de sessions: read",
                    "value": {
                      "detail": "This API key has no read access to sessions."
                    }
                  },
                  "Scoped key without decisions read": {
                    "summary": "La clé restreinte ne dispose pas de decisions: read",
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée, ou se trouve en dehors des limites de workflow ou réservées aux sessions approuvées d'une clé restreinte. La recherche de session s'exécute avant la vérification des identifiants, donc un `sessionId` inconnu renvoie `404` même sans clé valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID n'existe, ou elle a été supprimée",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside key limits": {
                    "summary": "La session se trouve en dehors des limites de workflow ou réservées aux sessions approuvées d'une clé restreinte",
                    "value": {
                      "detail": "Session not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 600 requêtes GET par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le quota.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/aml-screening-history/": {
      "get": {
        "summary": "Lister l'historique de filtrage AML",
        "description": "Lister chaque nouveau filtrage de surveillance continue terminé pour le contrôle AML d'une session, du plus récent au plus ancien selon `completed_at`, y compris les exécutions où rien n'a changé : les alertes, les entrées d'activité et les webhooks ne se déclenchent que lorsqu'un résultat évolue, cet historique constitue donc la preuve qu'un sujet sans alerte a bien continué d'être filtré. Fonctionne pour les identifiants de session KYC et KYB ; transmettez `node_id` lorsque la session a exécuté plusieurs étapes AML. Seuls les nouveaux filtrages de surveillance continue sont listés (le premier filtrage fait partie de la décision de session) et les exécutions antérieures à la création de cet historique ne sont pas reconstituées, de sorte qu'une session sans surveillance continue renvoie une liste vide. `count` est exact jusqu'à 100 et plafonné à 100 au-delà, suivez donc `next` jusqu'à ce qu'il soit `null`. Transmettez `month` pour lire un mois calendaire à la fois. Une clé API restreinte nécessite `decisions: read` ; voir [Surveillance AML continue](https://docs.didit.me/fr/core-technology/aml-screening/continuous-monitoring-aml-screening).",
        "operationId": "get_v3_session_aml_screening_history",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "list_aml_screening_history",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification (le `session_id` renvoyé par `POST /v3/session/`). Accepte les identifiants de session de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) : le serveur résout l'identifiant pour les deux types de session. Doit être un UUID bien formé ; une valeur malformée ne correspond pas à la route et renvoie une erreur HTML `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "ID de nœud du graphe de workflow du contrôle AML. Nécessaire uniquement lorsque la session a exécuté plusieurs étapes AML ; sans cela, le contrôle AML le plus récent est utilisé. Un nœud inconnu renvoie `404`.",
            "schema": {
              "type": "string",
              "example": "feature_aml_1"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Un mois civil UTC au format `YYYY-MM`. Seuls les filtrages effectués au cours de ce mois sont renvoyés ; sans ce paramètre, tous les mois sont renvoyés. Un mois mal formé renvoie `400`.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$",
              "example": "2026-09"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Nombre maximal d'exécutions de filtrage par page. Vaut par défaut 50. Une valeur inférieure à 1 ou non numérique revient à 50 ; une valeur supérieure à 1,000,000 renvoie `400`.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 1000000,
              "example": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Nombre de résultats à ignorer avant le premier renvoyé. La valeur par défaut est 0 ; une valeur négative ou non numérique revient à 0, une valeur supérieure à 1,000,000 renvoie `400`. Privilégiez l'utilisation des URL `next` et `previous`.",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 1000000,
              "example": 0
            }
          },
          {
            "name": "ordering",
            "in": "query",
            "required": false,
            "description": "Remplacement de tri optionnel. L'ordre par défaut est `-completed_at`. Transmettez le nom d'un champ de résultat (par exemple `completed_at`, `started_at`, `outcome` ou `score`) pour un tri croissant, préfixez-le par `-` pour un tri décroissant, et séparez plusieurs champs par des virgules. Les champs inconnus sont ignorés.",
            "schema": {
              "type": "string",
              "example": "completed_at"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/aml-screening-history/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.sessions.list_aml_screening_history(\n    \"11111111-2222-3333-4444-555555555555\",\n):\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.sessions.listAmlScreeningHistory(\"11111111-2222-3333-4444-555555555555\")) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Sessions.ListAMLScreeningHistoryAutoPaging(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsListAMLScreeningHistoryParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.sessions().listAmlScreeningHistory(\"11111111-2222-3333-4444-555555555555\")) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->sessions->listAmlScreeningHistory('11111111-2222-3333-4444-555555555555') as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.sessions.list_aml_screening_history(\"11111111-2222-3333-4444-555555555555\").auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Sessions.ListAmlScreeningHistoryAsync(\"11111111-2222-3333-4444-555555555555\"))\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page d'exécutions de filtrage, de la plus récente à la plus ancienne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "maximum": 100,
                      "description": "Nombre d'exécutions, exact jusqu'à 100 et plafonné à 100 au-delà."
                    },
                    "next": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de la page suivante, ou `null` sur la dernière page."
                    },
                    "previous": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL de la page précédente, ou `null` sur la première page."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AMLScreeningRun"
                      }
                    }
                  }
                },
                "examples": {
                  "Monitored subject": {
                    "value": {
                      "count": 2,
                      "next": null,
                      "previous": null,
                      "results": [
                        {
                          "uuid": "dddddddd-1111-2222-3333-444444444444",
                          "run_id": "aaaaaaaa-1111-2222-3333-444444444444",
                          "completed_at": "2026-09-14T04:12:33.481207Z",
                          "started_at": "2026-09-14T04:00:01.002311Z",
                          "outcome": "NO_CHANGE",
                          "trigger": "ONGOING_MONITORING",
                          "provider": "aml_data_source",
                          "status": "Approved",
                          "score": 0.0,
                          "total_hits": 0,
                          "new_hits": 0,
                          "entities_screened": 1,
                          "dataset_freshness": {
                            "captured_at": "2026-09-14T03:58:02.114820+00:00",
                            "provider": "aml_data_source",
                            "catalog_version": "2026-09-13",
                            "sources": {
                              "sanctions": {
                                "last_updated_at": "2026-09-13T21:10:00+00:00",
                                "oldest_updated_at": "2026-09-11T06:00:00+00:00",
                                "dataset_count": 120,
                                "dated_dataset_count": 120
                              },
                              "pep": {
                                "last_updated_at": "2026-09-13T08:00:00+00:00",
                                "oldest_updated_at": null,
                                "dataset_count": 45,
                                "dated_dataset_count": 44
                              },
                              "warnings": {
                                "last_updated_at": "2026-09-12T18:45:00+00:00",
                                "oldest_updated_at": "2026-09-01T00:00:00+00:00",
                                "dataset_count": 30,
                                "dated_dataset_count": 30
                              }
                            }
                          }
                        },
                        {
                          "uuid": "eeeeeeee-1111-2222-3333-444444444444",
                          "run_id": "bbbbbbbb-1111-2222-3333-444444444444",
                          "completed_at": "2026-09-13T04:11:58.020914Z",
                          "started_at": "2026-09-13T04:00:00.871022Z",
                          "outcome": "FAILED",
                          "trigger": "ONGOING_MONITORING",
                          "provider": "aml_data_source",
                          "status": "Approved",
                          "score": 0.0,
                          "total_hits": 0,
                          "new_hits": null,
                          "entities_screened": 0,
                          "dataset_freshness": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`limit` ou `offset` est supérieur à 1 000 000 (un tableau JSON avec un message), ou `month` n'est pas un mois calendaire `YYYY-MM` (un objet ayant pour clé `month`).",
            "content": {
              "application/json": {
                "examples": {
                  "Limit too large": {
                    "summary": "limit=2000000",
                    "value": [
                      "limit must not exceed 1000000."
                    ]
                  },
                  "Offset too large": {
                    "summary": "offset=2000000",
                    "value": [
                      "offset must not exceed 1000000."
                    ]
                  },
                  "Malformed month": {
                    "summary": "month=2026-13",
                    "value": {
                      "month": [
                        "Not a calendar month. Use YYYY-MM."
                      ]
                    }
                  }
                },
                "schema": {
                  "oneOf": [
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    {
                      "type": "object",
                      "properties": {
                        "month": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions read": {
                    "summary": "La clé restreinte ne dispose pas de decisions: read",
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée ou se trouve en dehors des limites d'une clé restreinte, ou elle ne comporte aucune vérification AML (pour le `node_id` indiqué). La recherche de session s'exécute avant la vérification des identifiants, donc un `sessionId` inconnu renvoie `404` même sans clé valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID n'existe, ou elle a été supprimée",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside key limits": {
                    "summary": "La session se trouve en dehors des limites d'une clé restreinte (également renvoyée pour une session supprimée il y a quelques instants)",
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "No AML check": {
                    "summary": "La session n'a jamais exécuté d'étape AML",
                    "value": {
                      "detail": "The session does not have an AML check."
                    }
                  },
                  "No AML check for node": {
                    "summary": "node_id ne correspond à aucune vérification AML de la session",
                    "value": {
                      "detail": "The session does not have an AML check for node 'feature_aml_2'."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 600 requêtes GET par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le quota.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/aml-screening-history/export/": {
      "get": {
        "summary": "Exporter l'historique de filtrage AML au format CSV",
        "description": "Télécharger le même historique de surveillance continue que `GET /v3/session/{sessionId}/aml-screening-history/` sous la forme d'un fichier CSV, à raison d'une ligne par nouveau filtrage terminé, de la plus récente à la plus ancienne, prêt à être transmis à un auditeur. Le fichier est transmis en continu dans son intégralité (sans pagination) et commence par une ligne d'en-tête ; une cellule vide signifie inconnue, les dates des jeux de données ne sont jamais estimées et une valeur débutant par une formule de tableur est précédée d'une apostrophe. Fonctionne pour les identifiants de session KYC et KYB ; transmettez `node_id` lorsque la session a exécuté plus d'une étape AML. Transmettez `month` pour exporter un mois civil. Les erreurs sont renvoyées au format JSON, et non CSV. Une clé API avec permissions restreintes nécessite `decisions: read` et `media: read` : la réponse étant un fichier, une clé sans `media: read` reçoit une erreur `403`.",
        "operationId": "get_v3_session_aml_screening_history_export",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "export_aml_screening_history",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification (le `session_id` renvoyé par `POST /v3/session/`). Accepte les identifiants de session de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) : le serveur résout l'identifiant pour les deux types de session. Doit être un UUID bien formé ; une valeur malformée ne correspond pas à la route et renvoie une erreur HTML `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "ID de nœud du graphe de workflow du contrôle AML. Nécessaire uniquement lorsque la session a exécuté plusieurs étapes AML ; sans cela, le contrôle AML le plus récent est utilisé. Un nœud inconnu renvoie `404`.",
            "schema": {
              "type": "string",
              "example": "feature_aml_1"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Un mois civil UTC au format `YYYY-MM`. Seuls les filtrages effectués au cours de ce mois sont renvoyés ; sans ce paramètre, tous les mois sont renvoyés. Un mois mal formé renvoie `400`.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$",
              "example": "2026-09"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/aml-screening-history/export/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -o aml-screening-history.csv"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.sessions.export_aml_screening_history(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nwith open(\"download.csv\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.sessions.exportAmlScreeningHistory(\"11111111-2222-3333-4444-555555555555\");\nawait writeFile(\"download.csv\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.Sessions.ExportAMLScreeningHistory(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsExportAMLScreeningHistoryParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.csv\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.sessions().exportAmlScreeningHistory(\"11111111-2222-3333-4444-555555555555\")\n        .writeTo(Path.of(\"download.csv\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->sessions->exportAmlScreeningHistory('11111111-2222-3333-4444-555555555555');\n$content->saveTo('download.csv');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.sessions.export_aml_screening_history(\"11111111-2222-3333-4444-555555555555\")\nFile.binwrite(\"download.csv\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.Sessions.ExportAmlScreeningHistoryAsync(\"11111111-2222-3333-4444-555555555555\");\nawait content.SaveToAsync(\"download.csv\");"
          }
        ],
        "responses": {
          "200": {
            "description": "Le fichier CSV, transmis sous forme de flux `text/csv` avec des sauts de ligne CRLF. Colonnes, dans l'ordre : `screened_at` (moment où le refiltrage s'est terminé), `outcome` (`NO_CHANGE`, `CHANGED` ou `FAILED`), `provider` (identifiant opaque de la source de données AML ; n'appliquez pas de logique conditionnelle dessus), `aml_status`, `aml_score`, `total_hits`, `datasets_captured_at`, `datasets_sanctions_last_updated_at`, `datasets_pep_last_updated_at`, `datasets_warnings_last_updated_at`, `datasets_adverse_media_last_updated_at`, `datasets_catalog_version`, `run_id` (l'exécution de surveillance), `entities_screened` (`1`, ou `0` pour une exécution échouée) et `new_hits` (vide si inconnu). Les dates sont au format ISO 8601 avec un décalage UTC. Une session sans refiltrage pour le moment renvoie uniquement la ligne d'en-tête.",
            "headers": {
              "Content-Disposition": {
                "description": "`attachment; filename=\"aml-screening-history-{sessionId}.csv\"`, ou `aml-screening-history-{sessionId}-{month}.csv` lorsque `month` est transmis.",
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=\"aml-screening-history-11111111-2222-3333-4444-555555555555.csv\""
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                },
                "example": "screened_at,outcome,provider,aml_status,aml_score,total_hits,datasets_captured_at,datasets_sanctions_last_updated_at,datasets_pep_last_updated_at,datasets_warnings_last_updated_at,datasets_adverse_media_last_updated_at,datasets_catalog_version,run_id,entities_screened,new_hits\r\n2026-09-14T04:12:33.481207+00:00,NO_CHANGE,aml_data_source,Approved,0.0,0,2026-09-14T03:58:02.114820+00:00,2026-09-13T21:10:00+00:00,2026-09-13T08:00:00+00:00,2026-09-12T18:45:00+00:00,,2026-09-13,aaaaaaaa-1111-2222-3333-444444444444,1,0\r\n2026-09-13T04:11:58.020914+00:00,FAILED,aml_data_source,Approved,0.0,0,,,,,,,bbbbbbbb-1111-2222-3333-444444444444,0,\r\n"
              }
            }
          },
          "400": {
            "description": "`month` n'est pas un mois calendaire `YYYY-MM`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "month": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "Malformed month": {
                    "summary": "month=2026-13",
                    "value": {
                      "month": [
                        "Not a calendar month. Use YYYY-MM."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions read": {
                    "summary": "La clé restreinte ne dispose pas de decisions: read",
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  },
                  "Scoped key without media read": {
                    "summary": "La clé restreinte ne dispose pas de media: read (la réponse est un fichier)",
                    "value": {
                      "detail": "This API key has no read access to media."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée ou se trouve en dehors des limites d'une clé restreinte, ou elle ne comporte aucune vérification AML (pour le `node_id` indiqué). La recherche de session s'exécute avant la vérification des identifiants, donc un `sessionId` inconnu renvoie `404` même sans clé valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID n'existe, ou elle a été supprimée",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside key limits": {
                    "summary": "La session se trouve en dehors des limites d'une clé restreinte (également renvoyée pour une session supprimée il y a quelques instants)",
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "No AML check": {
                    "summary": "La session n'a jamais exécuté d'étape AML",
                    "value": {
                      "detail": "The session does not have an AML check."
                    }
                  },
                  "No AML check for node": {
                    "summary": "node_id ne correspond à aucune vérification AML de la session",
                    "value": {
                      "detail": "The session does not have an AML check for node 'feature_aml_2'."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 600 requêtes GET par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le quota.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/add-images/": {
      "patch": {
        "summary": "Ajouter une image à une session",
        "description": "Ajoutez une image ou un PDF supplémentaire au résultat de vérification d'identité (`model_type=kyc`) ou de justificatif de domicile (`model_type=poa`) d'une session de vérification des utilisateurs (KYC) terminée, par exemple des éléments probants collectés en dehors du workflow. La session doit être `Approved`, `Declined`, `In Review` ou `Kyc Expired` et comporter le résultat désigné par `model_type` ; les sessions de vérification d'entreprise (KYB) ne sont pas prises en charge. Chaque appel ajoute un fichier (au résultat le plus récent lorsque l'étape a été exécutée plusieurs fois), conserve les fichiers existants et enregistre une entrée `FILE_ADDED` dans le journal d'activité de la session ; le téléversement n'envoie aucun webhook et ne modifie pas le statut de la session. Le fichier est compressé lors du téléversement et est renvoyé dans `extra_files` de la décision de la session. Cet endpoint est limité à 10 requêtes par minute et par clé API. Une clé API avec restriction de portée nécessite `sessions: write`, et sans `media: read`, elle reçoit les liens `extra_files` sous forme de `null`.",
        "operationId": "patch_v3_session_add_images",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "add_images",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification des utilisateurs (KYC) à laquelle ajouter le fichier (le `session_id` renvoyé par `POST /v3/session/`). Un identifiant de session de Vérification d'entreprise (KYB) renvoie `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file",
                  "model_type"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "L'image ou le PDF. Extensions autorisées : `jpg`, `jpeg`, `png`, `webp`, `tiff`, `pdf`. Au maximum 15 Mo lors du téléversement ; le fichier est ensuite compressé et rejeté avec `400` s'il dépasse toujours 2 Mo (2 097 152 octets). Les fichiers vides sont rejetés."
                  },
                  "model_type": {
                    "type": "string",
                    "enum": [
                      "kyc",
                      "poa"
                    ],
                    "description": "`kyc` ajoute le fichier au résultat de la vérification d'identité, `poa` au résultat du justificatif de domicile.",
                    "example": "kyc"
                  },
                  "file_password": {
                    "type": "string",
                    "description": "Mot de passe d'un PDF chiffré. Sans celui-ci, ou avec un mot de passe incorrect, un PDF chiffré renvoie `400`."
                  }
                }
              },
              "example": {
                "file": "(binary)",
                "model_type": "kyc"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/add-images/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'file=@./back-of-id.jpg' \\\n  -F 'model_type=kyc'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.add_images(\n    \"11111111-2222-3333-4444-555555555555\",\n    file=open(\"image.jpg\", \"rb\"),\n    model_type=\"kyc\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.addImages(\"11111111-2222-3333-4444-555555555555\", {\n  file: await fileFromPath(\"image.jpg\"),\n  model_type: \"kyc\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.AddImages(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsAddImagesParams{\n\tFile:      didit.FileFromPath(\"image.jpg\"),\n\tModelType: \"kyc\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\nimport me.didit.types.SessionsAddImagesParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().addImages(\"11111111-2222-3333-4444-555555555555\", SessionsAddImagesParams.builder()\n        .file(Path.of(\"image.jpg\"))\n        .modelType(SessionsAddImagesParams.ModelType.of(\"kyc\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->addImages('11111111-2222-3333-4444-555555555555', [\n    'file' => File::fromPath('image.jpg'),\n    'model_type' => 'kyc',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.add_images(\n  \"11111111-2222-3333-4444-555555555555\",\n  file: Pathname(\"image.jpg\"),\n  model_type: \"kyc\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.AddImagesAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsAddImagesParams\n{\n    File = FileUpload.FromPath(\"image.jpg\"),\n    ModelType = \"kyc\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Fichier ajouté. Renvoie tous les fichiers supplémentaires de ce résultat, y compris le nouveau.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "extra_files"
                  ],
                  "properties": {
                    "extra_files": {
                      "type": "array",
                      "description": "Liens pré-signés de courte durée vers tous les fichiers supplémentaires du résultat désigné par `model_type`, du plus ancien au plus récent. Chaque lien est `null` pour une clé API restreinte sans `media: read`. Lisez de nouveaux liens à partir de la décision de session ultérieurement.",
                      "items": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true
                      }
                    }
                  }
                },
                "example": {
                  "extra_files": [
                    "https://media.example.com/session/11111111-2222-3333-4444-555555555555/kyc-extra-files/66666666-7777-8888-9999-000000000000.jpg?expires=1789383731&signature=abc123"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation. Les erreurs de champ sont renvoyées sous la forme `{\"<field>\": [\"<message>\"]}` ; les erreurs de PDF chiffré sous la forme `{\"detail\": \"...\"}`.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing file": {
                    "summary": "Aucun champ de fichier dans le formulaire",
                    "value": {
                      "file": [
                        "No file was submitted."
                      ]
                    }
                  },
                  "Missing model_type": {
                    "summary": "model_type omis",
                    "value": {
                      "model_type": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid model_type": {
                    "summary": "model_type n'est ni kyc ni poa",
                    "value": {
                      "model_type": [
                        "\"passport\" is not a valid choice."
                      ]
                    }
                  },
                  "File too large": {
                    "summary": "Téléversement supérieur à 15 MB",
                    "value": {
                      "file": [
                        "File size should not exceed 15 MB"
                      ]
                    }
                  },
                  "Too large after compression": {
                    "summary": "Toujours supérieur à 2 MB après compression",
                    "value": {
                      "file": [
                        "File size is too big. Max allowed size is 2097152 bytes."
                      ]
                    }
                  },
                  "Encrypted PDF": {
                    "summary": "PDF chiffré sans file_password",
                    "value": {
                      "detail": "The PDF is encrypted. Please upload a decrypted PDF or a photo instead."
                    }
                  },
                  "Wrong PDF password": {
                    "summary": "file_password n'ouvre pas le PDF",
                    "value": {
                      "detail": "The PDF password is incorrect. Please provide the correct password."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without sessions write": {
                    "summary": "La clé restreinte ne dispose pas de sessions: write",
                    "value": {
                      "detail": "This API key has no write access to sessions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée ou se trouve en dehors des limites d'une clé restreinte ; il s'agit d'une session KYB ou elle n'est pas dans l'état `Approved`, `Declined`, `In Review` ou `Kyc Expired` ; ou elle n'a aucun résultat pour le `model_type` demandé (vérifié avant la validation du fichier). La recherche de session s'exécute avant la vérification des identifiants, donc un `sessionId` inconnu renvoie `404` même sans clé valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID n'existe, ou elle a été supprimée",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside key limits": {
                    "summary": "La session se trouve en dehors des limites de workflow ou réservées aux sessions approuvées d'une clé restreinte",
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "Not eligible": {
                    "summary": "Session pas encore terminée, ou ID de session KYB",
                    "value": {
                      "detail": "No Session matches the given query."
                    }
                  },
                  "No ID verification": {
                    "summary": "model_type=kyc sur une session sans Vérification d'identité",
                    "value": {
                      "detail": "The session does not have KYC data."
                    }
                  },
                  "No Proof of Address": {
                    "summary": "model_type=poa sur une session sans Justificatif de domicile",
                    "value": {
                      "detail": "The session does not have POA data."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 10 requêtes d'ajout d'images par minute par clé API (les requêtes rejetées comptent également). Le budget partagé de 300 requêtes d'écriture par minute s'applique aussi. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Session add-images rate limit exceeded. You can make up to 10 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/DocumentProcessingBusy"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/update-aml-status/": {
      "patch": {
        "summary": "Mettre à jour le statut d'une vérification AML",
        "description": "Définissez le statut du contrôle de filtrage AML d'une session dans son ensemble (le `status` d'une entrée `aml_screenings[]` dans la décision de la session), par exemple `Approved` après que votre équipe a écarté chaque résultat. Fonctionne pour les identifiants de session KYC et KYB ; transmettez `node_id` (paramètre de requête ou champ du corps) lorsque la session a exécuté plusieurs étapes AML, sinon le contrôle AML le plus récent est mis à jour. Lorsque le statut change effectivement, une entrée d'activité `AML_STATUS_UPDATED` est enregistrée et un [webhook](https://docs.didit.me/fr/integration/webhooks) `data.updated` est envoyé ; envoyer le statut actuel renvoie `200` et ne modifie rien. Le statut de la session n'est pas recalculé : utilisez `PATCH /v3/session/{sessionId}/update-status/` pour la décision de la session et `PATCH /v3/session/{sessionId}/update-aml-hit-status/` pour les résultats individuels. Une clé API avec périmètre restreint nécessite `decisions: write`.",
        "operationId": "patch_v3_session_update_aml_status",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_aml_status",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification (le `session_id` renvoyé par `POST /v3/session/`). Accepte les identifiants de session de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) : le serveur résout l'identifiant pour les deux types de session. Doit être un UUID bien formé ; une valeur malformée ne correspond pas à la route et renvoie une erreur HTML `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "ID de nœud du graphe de workflow du contrôle AML à mettre à jour. Nécessaire uniquement lorsque la session a exécuté plusieurs étapes AML. Prévaudra sur `node_id` dans le corps.",
            "schema": {
              "type": "string",
              "example": "feature_aml_1"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "Not Finished",
                      "Approved",
                      "Declined",
                      "In Review",
                      "Resub Requested"
                    ],
                    "description": "Nouveau statut de la vérification AML.",
                    "example": "Approved"
                  },
                  "node_id": {
                    "type": "string",
                    "description": "ID de nœud du graphe de workflow du contrôle AML, comme alternative au paramètre de requête.",
                    "example": "feature_aml_1"
                  }
                }
              },
              "example": {
                "status": "Approved"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PATCH 'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/update-aml-status/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"status\": \"Approved\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_aml_status(\n    \"11111111-2222-3333-4444-555555555555\",\n    status=\"Approved\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateAmlStatus(\"11111111-2222-3333-4444-555555555555\", {\n  status: \"Approved\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateAMLStatus(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsUpdateAMLStatusParams{\n\tStatus: \"Approved\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsUpdateAmlStatusParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateAmlStatus(\"11111111-2222-3333-4444-555555555555\", SessionsUpdateAmlStatusParams.builder()\n        .status(SessionsUpdateAmlStatusParams.Status.of(\"Approved\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateAmlStatus('11111111-2222-3333-4444-555555555555', [\n    'status' => 'Approved',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_aml_status(\n  \"11111111-2222-3333-4444-555555555555\",\n  status: \"Approved\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateAmlStatusAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsUpdateAmlStatusParams\n{\n    Status = \"Approved\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Statut de vérification AML défini (ou inchangé lorsqu'il avait déjà cette valeur).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "status",
                    "previous_status"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Toujours `AML status updated successfully`."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "Not Finished",
                        "Approved",
                        "Declined",
                        "In Review",
                        "Resub Requested"
                      ],
                      "description": "Statut du contrôle AML actuel."
                    },
                    "previous_status": {
                      "type": "string",
                      "enum": [
                        "Not Finished",
                        "Approved",
                        "Declined",
                        "In Review",
                        "Resub Requested"
                      ],
                      "description": "Statut avant l'appel. Égal à `status` lorsque rien n'a changé."
                    }
                  }
                },
                "example": {
                  "message": "AML status updated successfully",
                  "status": "Approved",
                  "previous_status": "In Review"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation : `status` manquant ou ne faisant pas partie des valeurs autorisées. La recherche de vérification AML s'exécute en premier, donc une session sans vérification AML renvoie `404` même avec un corps invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Missing status": {
                    "summary": "Corps vide ou aucun statut",
                    "value": {
                      "status": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid status": {
                    "summary": "status n'est pas dans l'enum",
                    "value": {
                      "status": [
                        "\"Cleared\" is not a valid choice."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée ou se trouve en dehors des limites d'une clé restreinte, ou elle ne comporte aucune vérification AML (pour le `node_id` indiqué). La recherche de session s'exécute avant la vérification des identifiants, donc un `sessionId` inconnu renvoie `404` même sans clé valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Unknown session": {
                    "summary": "Aucune session avec cet ID n'existe, ou elle a été supprimée",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Outside key limits": {
                    "summary": "La session se trouve en dehors des limites d'une clé restreinte (également renvoyée pour une session supprimée il y a quelques instants)",
                    "value": {
                      "detail": "Session not found."
                    }
                  },
                  "No AML check": {
                    "summary": "La session n'a jamais exécuté d'étape AML",
                    "value": {
                      "detail": "The session does not have an AML check."
                    }
                  },
                  "No AML check for node": {
                    "summary": "node_id ne correspond à aucune vérification AML de la session",
                    "value": {
                      "detail": "The session does not have an AML check for node 'feature_aml_2'."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 300 requêtes d'écriture (POST, PATCH, DELETE) par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/status/": {
      "get": {
        "summary": "Obtenir l'état du service (public, non authentifié)",
        "description": "Renvoie l'état de chaque service Didit (`operational`, `degraded` ou `down`), l'état global (le pire d'entre eux) et les incidents en cours ou résolus au cours des 7 derniers jours. Utilisez-le pour alimenter un widget de statut ou pour vérifier l'état de Didit depuis votre intégration.\n\nPublic : n'envoyez aucun en-tête d'authentification. La réponse ne contient aucune donnée d'organisation et est identique pour chaque appelant. Les réponses sont mises en cache pendant 30 secondes, n'effectuez donc pas d'appels plus d'une fois toutes les 30 secondes.",
        "operationId": "get_v3_status",
        "tags": [
          "Status"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "État actuel du service.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceStatusFeed"
                },
                "examples": {
                  "One service degraded": {
                    "summary": "Un incident en cours et un incident résolu cette semaine",
                    "value": {
                      "status": "degraded",
                      "updated_at": "2026-10-13T09:41:07.512345Z",
                      "services": [
                        {
                          "key": "service_id_verification",
                          "name": "ID verification",
                          "status": "operational"
                        },
                        {
                          "key": "service_liveness_face_match",
                          "name": "Liveness and face match",
                          "status": "operational"
                        },
                        {
                          "key": "service_aml_screening",
                          "name": "AML screening",
                          "status": "operational"
                        },
                        {
                          "key": "service_kyb_registries",
                          "name": "KYB registries",
                          "status": "operational"
                        },
                        {
                          "key": "service_database_validation",
                          "name": "Database validation",
                          "status": "degraded"
                        },
                        {
                          "key": "service_phone_delivery",
                          "name": "Phone verification delivery",
                          "status": "operational"
                        },
                        {
                          "key": "service_email_delivery",
                          "name": "Email verification delivery",
                          "status": "operational"
                        },
                        {
                          "key": "service_transaction_monitoring",
                          "name": "Transaction monitoring",
                          "status": "operational"
                        }
                      ],
                      "incidents": [
                        {
                          "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                          "service": "service_database_validation",
                          "service_name": "Database validation",
                          "state": "degraded",
                          "status": "ongoing",
                          "title": "Database validation is degraded in Brazil.",
                          "body": "Checks against Brazil (CPF) may be slow or fail since 08:55 UTC.",
                          "affected": "Brazil (CPF)",
                          "country_name": "Brazil",
                          "started_at": "2026-10-13T08:55:00Z",
                          "resolved_at": null,
                          "duration_minutes": null
                        },
                        {
                          "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
                          "service": "service_aml_screening",
                          "service_name": "AML screening",
                          "state": "down",
                          "status": "resolved",
                          "title": "AML screening is back to normal.",
                          "body": "Recovered at 14:32 UTC after 17 minutes.",
                          "affected": "",
                          "country_name": "",
                          "started_at": "2026-10-11T14:15:00Z",
                          "resolved_at": "2026-10-11T14:32:00Z",
                          "duration_minutes": 17
                        }
                      ]
                    }
                  },
                  "All operational": {
                    "summary": "Aucun incident au cours des 7 derniers jours",
                    "value": {
                      "status": "operational",
                      "updated_at": "2026-10-13T09:41:07.512345Z",
                      "services": [
                        {
                          "key": "service_id_verification",
                          "name": "ID verification",
                          "status": "operational"
                        },
                        {
                          "key": "service_liveness_face_match",
                          "name": "Liveness and face match",
                          "status": "operational"
                        },
                        {
                          "key": "service_aml_screening",
                          "name": "AML screening",
                          "status": "operational"
                        },
                        {
                          "key": "service_kyb_registries",
                          "name": "KYB registries",
                          "status": "operational"
                        },
                        {
                          "key": "service_database_validation",
                          "name": "Database validation",
                          "status": "operational"
                        },
                        {
                          "key": "service_phone_delivery",
                          "name": "Phone verification delivery",
                          "status": "operational"
                        },
                        {
                          "key": "service_email_delivery",
                          "name": "Email verification delivery",
                          "status": "operational"
                        },
                        {
                          "key": "service_transaction_monitoring",
                          "name": "Transaction monitoring",
                          "status": "operational"
                        }
                      ],
                      "incidents": []
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Plus de 600 requêtes GET en une minute depuis la même adresse IP (ou la même clé API, si vous en envoyez une). Respectez `Retry-After` avant de réessayer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "detail"
                  ],
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "GET request rate limit exceeded. You can make up to 600 requests per minute."
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -fsS https://verification.didit.me/v3/status/"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import requests\n\nresp = requests.get('https://verification.didit.me/v3/status/', timeout=5)\nresp.raise_for_status()\nfeed = resp.json()\nprint(feed['status'])\nfor service in feed['services']:\n    if service['status'] != 'operational':\n        print(service['key'], service['status'])"
          },
          {
            "lang": "javascript",
            "label": "JavaScript",
            "source": "const feed = await fetch('https://verification.didit.me/v3/status/').then((r) => r.json());\nconsole.log(feed.status);\nconst affected = feed.services.filter((s) => s.status !== 'operational');\nconsole.log(affected.map((s) => `${s.key}: ${s.status}`));"
          }
        ],
        "x-didit-sdk": {
          "resource": "system",
          "method": "retrieve_status",
          "auth": "public",
          "server": false
        }
      }
    },
    "/v3/organization/bank-verification-pricing/": {
      "get": {
        "summary": "Obtenir les prix de vérification bancaire (publics, sans authentification)",
        "description": "Renvoie le prix catalogue de chaque méthode de Vérification bancaire dans chaque pays : la connexion bancaire avec ses modules complémentaires de solde et de transactions, ainsi que la vérification de compte. Une méthode qu'un pays ne propose pas aujourd'hui apparaît comme non disponible, sans prix. Utilisez-le pour obtenir un devis pour une étape bancaire avant de concevoir un workflow, ou pour afficher les prix bancaires dans votre propre produit.\n\nPublic : n'envoyez aucun en-tête d'authentification. La réponse ne contient aucune donnée d'organisation et est identique pour chaque appelant. Elle est mise en cache publiquement pendant une heure et comporte un `ETag` ; envoyez donc `If-None-Match` pour recevoir un `304 Not Modified` lorsque rien n'a changé.\n\nUne méthode est `available` uniquement là où Didit la propose en production aujourd'hui, et son `price_usd` est `null` partout ailleurs, afin que le flux n'affiche jamais un prix dont vous ne pouvez pas bénéficier. `available: false` couvre un pays sans prix approuvé, une méthode non prise en charge par le pays et un routage pas encore activé.\n\nIl s'agit de prix catalogue avant la remise de votre forfait. La remise de votre forfait s'applique à l'ensemble du prix bancaire, et un prix négocié ou contractuel remplace le prix catalogue pour votre organisation.",
        "operationId": "get_v3_bank_verification_pricing",
        "tags": [
          "Pricing"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -fsS https://verification.didit.me/v3/organization/bank-verification-pricing/"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# This call needs no API key.\nclient = Didit()\n\nresult = client.pricing.bank_verification()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// This call needs no API key.\nconst didit = new Didit();\n\nconst result = await didit.pricing.bankVerification();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// This call needs no API key.\nclient := didit.NewClient()\n\nresult, err := client.Pricing.BankVerification(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// This call needs no API key.\nDidit client = new Didit();\n\nvar result = client.pricing().bankVerification();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// This call needs no API key.\n$didit = new DiditClient();\n\n$result = $didit->pricing->bankVerification();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# This call needs no API key.\ndidit = Didit::Client.new\n\nresult = didit.pricing.bank_verification\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// This call needs no API key.\nusing var client = new DiditClient();\n\nvar result = await client.Pricing.BankVerificationAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-sdk": {
          "resource": "pricing",
          "method": "bank_verification",
          "auth": "none",
          "server": true
        },
        "responses": {
          "200": {
            "description": "Prix publics de vérification bancaire par pays.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BankVerificationPricing"
                },
                "examples": {
                  "Two countries": {
                    "summary": "Un pays avec les deux méthodes, un sans aucune",
                    "value": {
                      "currency": "USD",
                      "statement_upload": {
                        "price_usd": "0.0000",
                        "included_after_charged_bank_attempt": true,
                        "standalone_available": false
                      },
                      "own_provider_fee_usd": "0.0200",
                      "countries": {
                        "GBR": {
                          "name": "United Kingdom",
                          "methods": {
                            "open_banking": {
                              "available": true,
                              "market": "UK and EEA",
                              "price_usd": "0.7900",
                              "add_ons": {
                                "balance": "0.3500",
                                "transactions": "1.3000"
                              }
                            },
                            "account_lookup": {
                              "available": true,
                              "price_usd": "0.4000"
                            }
                          }
                        },
                        "CAN": {
                          "name": "Canada",
                          "methods": {
                            "open_banking": {
                              "available": false,
                              "market": null,
                              "price_usd": null,
                              "add_ons": {}
                            },
                            "account_lookup": {
                              "available": false,
                              "price_usd": null
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "304": {
            "description": "Non modifié : l'`ETag` envoyé dans `If-None-Match` correspond toujours. Aucun corps de réponse."
          }
        }
      }
    },
    "/v3/session/{sessionId}/simulate/": {
      "post": {
        "summary": "Simuler le statut d'une session de sandbox",
        "description": "Forcez un statut terminal sur une session sandbox après coup, depuis votre backend, sans exécuter le workflow. Applications sandbox uniquement : une session de production renvoie `404`. Fonctionne pour les sessions de vérification des utilisateurs (KYC) et de vérification d'entreprise (KYB).\n\nDéfinissez `new_status`, ou laissez `scenario` ou `risk` le fournir. `risk` (ou le premier risque porté par les valeurs magiques du scénario) ajoute cet avertissement à la session. La modification est consignée dans l'activité de la session.\n\n`send_webhooks` (`true` par défaut) envoie exactement les webhooks qu'un véritable changement de statut envoie. Avec `false`, le statut change quand même et la console se met toujours à jour en direct, mais aucun webhook n'est consigné ni envoyé, la récupération des webhooks manqués ne renvoie jamais cette décision, et le changement de statut suivant envoie les webhooks comme d'habitude. La réponse renvoie en écho la valeur appliquée.\n\nNécessite le privilège `write:sessions` ; une clé API restreinte nécessite un accès en écriture aux sessions. Un `session_id` inconnu renvoie `404` et la session d'une autre application renvoie `403`, tous deux avant que le corps ne soit lu ; une session de production ne renvoie `404` qu'après validation du corps. Pour simuler depuis le workflow hébergé avec le propre token de la session, utilisez `POST /v3/session/{sessionId}/sandbox/simulate/`. Consultez [Sandbox et données de test](/fr/integration/sandbox-testing) pour le catalogue de scénarios.",
        "operationId": "post_v3_session_simulate",
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification sandbox. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxSimulateRequest"
              },
              "examples": {
                "Scenario Without Webhooks": {
                  "summary": "Refuser via un scénario sans envoyer de webhooks",
                  "value": {
                    "scenario": "decline_aml_hit",
                    "send_webhooks": false
                  }
                },
                "Status Only": {
                  "summary": "Approuver et envoyer les webhooks habituels",
                  "value": {
                    "new_status": "Approved"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Le statut a changé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxSimulateResponse"
                },
                "examples": {
                  "Simulated": {
                    "summary": "Refusé via un scénario, webhooks non envoyés",
                    "value": {
                      "session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "previous_status": "In Progress",
                      "status": "Declined",
                      "scenario": "decline_aml_hit",
                      "risk": "POSSIBLE_MATCH_FOUND",
                      "send_webhooks": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation : un scénario inconnu ou un risque inconnu, absence de `new_status` lorsque ni `scenario` ni `risk` n'en fournissent un, un statut que cet endpoint ne définit pas, ou la session possède déjà le statut demandé (un tableau JSON brut).",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown Scenario": {
                    "summary": "le scénario ne figure pas dans le catalogue",
                    "value": {
                      "scenario": [
                        "Unknown sandbox scenario: 'not-a-scenario'."
                      ]
                    }
                  },
                  "Unknown Risk": {
                    "summary": "risk ne figure pas dans le catalogue",
                    "value": {
                      "risk": [
                        "Unknown sandbox risk case: 'NOT_A_RISK'."
                      ]
                    }
                  },
                  "Missing new_status": {
                    "summary": "Aucun new_status, scénario ou risque",
                    "value": {
                      "new_status": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid new_status": {
                    "summary": "Un statut que la simulation ne définit pas",
                    "value": {
                      "new_status": [
                        "\"Resubmitted\" is not a valid choice."
                      ]
                    }
                  },
                  "Same Status": {
                    "summary": "La session possède déjà ce statut",
                    "value": [
                      "The new status is the same as the current status."
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API Key": {
                    "summary": "Clé API restreinte ayant dépassé sa date d'expiration",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, appelant sans le privilège `write:sessions`, clé API avec restriction de portée ne disposant pas de l'accès requis par cet endpoint, ou un `session_id` qui appartient à une autre application.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'appelant n'a pas write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped Key Without Access": {
                    "summary": "Clé API restreinte sans cet accès",
                    "value": {
                      "detail": "This API key has no write access to sessions."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session avec ce `session_id` n'existe, ou il s'agit d'une session de production (hors sandbox).",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "Session inconnue ou active",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST \\\n  https://verification.didit.me/v3/session/3fa85f64-5717-4562-b3fc-2c963f66afa6/simulate/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"scenario\": \"decline_aml_hit\", \"send_webhooks\": false}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.simulate(\n    \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    scenario=\"decline_aml_hit\",\n    send_webhooks=False,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.simulate(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  scenario: \"decline_aml_hit\",\n  send_webhooks: false,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Simulate(ctx, \"3fa85f64-5717-4562-b3fc-2c963f66afa6\", didit.SandboxSimulateRequest{\n\tScenario:     didit.String(\"decline_aml_hit\"),\n\tSendWebhooks: didit.Bool(false),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SandboxSimulateRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().simulate(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", SandboxSimulateRequest.builder()\n        .scenario(\"decline_aml_hit\")\n        .sendWebhooks(false)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->simulate('3fa85f64-5717-4562-b3fc-2c963f66afa6', [\n    'scenario' => 'decline_aml_hit',\n    'send_webhooks' => false,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.simulate(\n  \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  scenario: \"decline_aml_hit\",\n  send_webhooks: false\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.SimulateAsync(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", new SandboxSimulateRequest\n{\n    Scenario = \"decline_aml_hit\",\n    SendWebhooks = false,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "simulate",
          "auth": "api_key",
          "server": true
        }
      }
    },
    "/v3/session/{sessionId}/sandbox/simulate/": {
      "post": {
        "summary": "Simuler le statut d'une session de sandbox depuis le client",
        "description": "La même simulation que `POST /v3/session/{sessionId}/simulate/`, authentifiée avec le `Session-Token` propre à la session (renvoyé dans `session_token` par [Create Session](/fr/sessions-api/create-session)) au lieu de votre clé API, afin qu'un banc de test ou le flux hébergé puisse l'appeler depuis le client. Le corps, la réponse et `send_webhooks` se comportent exactement comme sur cet endpoint.\n\nUn `Session-Token` d'une application en production (hors sandbox), ou un jeton qui ne correspond pas au `sessionId` dans le chemin, renvoie `404`. Voir [Sandbox & Test Data](/fr/integration/sandbox-testing).",
        "operationId": "post_v3_session_sandbox_simulate",
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification sandbox. Doit correspondre à la session encodée dans le Session-Token utilisé pour s'authentifier.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxSimulateRequest"
              },
              "examples": {
                "Scenario Without Webhooks": {
                  "summary": "Refuser via un scénario sans envoyer de webhooks",
                  "value": {
                    "scenario": "decline_aml_hit",
                    "send_webhooks": false
                  }
                },
                "Status Only": {
                  "summary": "Approuver et envoyer les webhooks habituels",
                  "value": {
                    "new_status": "Approved"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Le statut a changé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxSimulateResponse"
                },
                "examples": {
                  "Simulated": {
                    "summary": "Refusé via un scénario, webhooks non envoyés",
                    "value": {
                      "session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "previous_status": "In Progress",
                      "status": "Declined",
                      "scenario": "decline_aml_hit",
                      "risk": "POSSIBLE_MATCH_FOUND",
                      "send_webhooks": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation : un scénario inconnu ou un risque inconnu, absence de `new_status` lorsque ni `scenario` ni `risk` n'en fournissent un, un statut que cet endpoint ne définit pas, ou la session possède déjà le statut demandé (un tableau JSON brut).",
            "content": {
              "application/json": {
                "examples": {
                  "Unknown Scenario": {
                    "summary": "le scénario ne figure pas dans le catalogue",
                    "value": {
                      "scenario": [
                        "Unknown sandbox scenario: 'not-a-scenario'."
                      ]
                    }
                  },
                  "Unknown Risk": {
                    "summary": "risk ne figure pas dans le catalogue",
                    "value": {
                      "risk": [
                        "Unknown sandbox risk case: 'NOT_A_RISK'."
                      ]
                    }
                  },
                  "Missing new_status": {
                    "summary": "Aucun new_status, scénario ou risque",
                    "value": {
                      "new_status": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid new_status": {
                    "summary": "Un statut que la simulation ne définit pas",
                    "value": {
                      "new_status": [
                        "\"Resubmitted\" is not a valid choice."
                      ]
                    }
                  },
                  "Same Status": {
                    "summary": "La session possède déjà ce statut",
                    "value": [
                      "The new status is the same as the current status."
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "L'en-tête `Session-Token` est manquant ou invalide.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Session Token": {
                    "summary": "Session-Token manquant ou invalide",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Le `Session-Token` appartient à une application de production (non sandbox), ou ne correspond pas au `sessionId` dans le chemin.",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "Session en production, ou non-concordance session_id / token",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST \\\n  https://verification.didit.me/v3/session/3fa85f64-5717-4562-b3fc-2c963f66afa6/sandbox/simulate/ \\\n  -H 'Session-Token: YOUR_SESSION_TOKEN' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"new_status\": \"Approved\", \"send_webhooks\": false}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import requests\n\nresponse = requests.post(\n    \"https://verification.didit.me/v3/session/3fa85f64-5717-4562-b3fc-2c963f66afa6/sandbox/simulate/\",\n    headers={\"Session-Token\": \"YOUR_SESSION_TOKEN\"},\n    json={\"new_status\": \"Approved\", \"send_webhooks\": False},\n)\nresponse.raise_for_status()\nprint(response.json())"
          }
        ],
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "simulate_sandbox",
          "auth": "device_token",
          "server": false
        }
      }
    },
    "/v3/session/{sessionId}/features/overrides/": {
      "get": {
        "summary": "Lister les dérogations aux contrôles d'une session",
        "description": "Chaque dérogation au statut d'une fonctionnalité individuelle (étape) lors d'une session de Vérification des utilisateurs (KYC) ou de Vérification d'entreprise (KYB), de la plus récente à la plus ancienne et sans pagination : celles appliquées, celles en attente que la personne termine le flux (`pending_until_flow_finishes`) et celles annulées, chacune indiquant qui l'a demandée, son motif, et si elle s'est appliquée alors que la personne était encore dans le flux (`forced`).\n\n`person_in_flow` indique si une nouvelle dérogation avec `defer_until_flow_finishes: true` serait mise en attente. `flow_finished_at` indique la dernière fois que la personne a terminé le flux ; il vaut `null` tant qu'elle y est encore (nouvelle soumission comprise) et lorsque la session s'est terminée avant qu'elle n'ait fini.\n\nNécessite le privilège `read:sessions` ; une clé API avec restriction de portée nécessite un accès en lecture aux décisions.",
        "operationId": "get_v3_session_feature_overrides",
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Les dérogations aux vérifications de la session, de la plus récente à la plus ancienne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "session_id",
                    "person_in_flow",
                    "flow_finished_at",
                    "overrides"
                  ],
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "format": "uuid",
                      "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
                    },
                    "person_in_flow": {
                      "type": "boolean",
                      "description": "Indique si la personne est toujours dans le flux, de sorte qu'une nouvelle dérogation avec `defer_until_flow_finishes: true` se mettrait en attente.",
                      "example": true
                    },
                    "flow_finished_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Moment où la personne a terminé le flux pour la dernière fois. `null` tant qu'elle s'y trouve encore (nouvelle soumission incluse) et lorsque la session s'est fermée avant qu'elle n'ait terminé (abandonnée, expirée ou lorsqu'une décision a été prise en cours de flux).",
                      "example": null
                    },
                    "overrides": {
                      "type": "array",
                      "description": "Chaque dérogation de la session, de la plus récente à la plus ancienne.",
                      "items": {
                        "$ref": "#/components/schemas/FeatureStatusOverride"
                      }
                    }
                  }
                },
                "examples": {
                  "Overrides": {
                    "summary": "Un override en attente, un override appliqué",
                    "value": {
                      "session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "person_in_flow": true,
                      "flow_finished_at": null,
                      "overrides": [
                        {
                          "id": "9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3",
                          "node_id": "feature_liveness_1",
                          "feature_type": "",
                          "feature_model": "Face",
                          "previous_status": "Declined",
                          "new_status": "Approved",
                          "state": "pending_until_flow_finishes",
                          "forced": false,
                          "reason": "Liveness retried with a reviewer present.",
                          "requested_by": {
                            "email": "reviewer@example.com",
                            "name": "Alex Reviewer",
                            "type": "CONSOLE_USER"
                          },
                          "requested_at": "2026-10-13T09:15:00Z",
                          "applied_at": null,
                          "cancelled_at": null,
                          "cancel_reason": null
                        },
                        {
                          "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
                          "node_id": "feature_ocr_1",
                          "feature_type": "",
                          "feature_model": "KYC",
                          "previous_status": "In Review",
                          "new_status": "Approved",
                          "state": "applied",
                          "forced": true,
                          "reason": "Document manually verified by compliance.",
                          "requested_by": {
                            "email": "reviewer@example.com",
                            "name": "Alex Reviewer",
                            "type": "CONSOLE_USER"
                          },
                          "requested_at": "2026-10-13T09:15:00Z",
                          "applied_at": "2026-10-13T09:15:00Z",
                          "cancelled_at": null,
                          "cancel_reason": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API Key": {
                    "summary": "Clé API restreinte ayant dépassé sa date d'expiration",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, appelant sans le privilège `read:sessions`, clé API avec restriction de portée ne disposant pas de l'accès requis par cet endpoint, ou un `session_id` qui appartient à une autre application.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'appelant n'a pas read:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped Key Without Access": {
                    "summary": "Clé API restreinte sans cet accès",
                    "value": {
                      "detail": "This API key has no read access to decisions."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session KYC ou KYB avec ce `session_id` n'existe.",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "session_id inconnu",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET \\\n  https://verification.didit.me/v3/session/3fa85f64-5717-4562-b3fc-2c963f66afa6/features/overrides/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.list_feature_overrides(\n    \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.listFeatureOverrides(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.ListFeatureOverrides(ctx, \"3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().listFeatureOverrides(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->listFeatureOverrides('3fa85f64-5717-4562-b3fc-2c963f66afa6');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.list_feature_overrides(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.ListFeatureOverridesAsync(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "list_feature_overrides",
          "auth": "api_key",
          "server": true
        }
      }
    },
    "/v3/session/{sessionId}/features/overrides/{overrideId}/cancel/": {
      "post": {
        "summary": "Annuler une dérogation de vérification en attente de la fin du flux",
        "description": "Annuler une dérogation sur le statut d'une fonctionnalité (étape) qui est encore `pending_until_flow_finishes`, afin qu'elle ne s'applique jamais. La vérification conserve son statut, l'annulation est consignée dans l'activité de la session sous `FEATURE_OVERRIDE_CANCELLED`, et aucun webhook n'est envoyé. La réponse est la dérogation avec `state: cancelled` et `cancel_reason: cancelled_by_reviewer`.\n\nUne dérogation déjà appliquée ou annulée renvoie `409` avec le code `feature_override_not_pending`. Recherchez les identifiants de dérogation à l'aide de `GET /v3/session/{sessionId}/features/overrides/` ou dans le champ `override` renvoyé par la mise à jour du statut de la fonctionnalité.\n\nNécessite le privilège `write:sessions` ; une clé API restreinte nécessite un accès en écriture aux décisions.",
        "operationId": "post_v3_session_feature_override_cancel",
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            }
          },
          {
            "in": "path",
            "name": "overrideId",
            "required": true,
            "description": "L'`id` de la dérogation à annuler.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La dérogation est annulée et ne s'appliquera jamais.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeatureStatusOverride"
                },
                "examples": {
                  "Cancelled": {
                    "summary": "La dérogation annulée",
                    "value": {
                      "id": "9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3",
                      "node_id": "feature_liveness_1",
                      "feature_type": "",
                      "feature_model": "Face",
                      "previous_status": "Declined",
                      "new_status": "Approved",
                      "state": "cancelled",
                      "forced": false,
                      "reason": "Liveness retried with a reviewer present.",
                      "requested_by": {
                        "email": "reviewer@example.com",
                        "name": "Alex Reviewer",
                        "type": "CONSOLE_USER"
                      },
                      "requested_at": "2026-10-13T09:15:00Z",
                      "applied_at": null,
                      "cancelled_at": "2026-10-13T09:20:00Z",
                      "cancel_reason": "cancelled_by_reviewer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API Key": {
                    "summary": "Clé API restreinte ayant dépassé sa date d'expiration",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, appelant sans le privilège `write:sessions`, clé API avec restriction de portée ne disposant pas de l'accès requis par cet endpoint, ou un `session_id` qui appartient à une autre application.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'appelant n'a pas write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped Key Without Access": {
                    "summary": "Clé API restreinte sans cet accès",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session KYC ou KYB avec ce `session_id` n'existe, ou la session ne comporte aucun remplacement avec cet `overrideId`.",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "session_id inconnu",
                    "value": {
                      "detail": "Not found."
                    }
                  },
                  "Override Not Found": {
                    "summary": "Aucune dérogation avec cet identifiant sur la session",
                    "value": {
                      "detail": "Override not found."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "La dérogation a déjà été appliquée ou a été annulée.",
            "content": {
              "application/json": {
                "examples": {
                  "Not Pending": {
                    "summary": "Seule une dérogation en attente peut être annulée",
                    "value": {
                      "detail": "This override is no longer pending: it already applied or was cancelled.",
                      "code": "feature_override_not_pending"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST \\\n  https://verification.didit.me/v3/session/3fa85f64-5717-4562-b3fc-2c963f66afa6/features/overrides/9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3/cancel/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.cancel_feature_override(\n    \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    \"9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.cancelFeatureOverride(\n  \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  \"9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.CancelFeatureOverride(ctx, \"3fa85f64-5717-4562-b3fc-2c963f66afa6\", \"9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().cancelFeatureOverride(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", \"9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->cancelFeatureOverride('3fa85f64-5717-4562-b3fc-2c963f66afa6', '9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.cancel_feature_override(\n  \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  \"9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.CancelFeatureOverrideAsync(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", \"9b2f4c1e-8d3a-4e5f-a6b7-c8d9e0f1a2b3\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "cancel_feature_override",
          "auth": "api_key",
          "server": true
        }
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/tags/add/": {
      "post": {
        "summary": "Ajouter un tag à un réseau",
        "description": "Associe l'un des tags de votre application au réseau. Renvoie les détails du réseau, dont `tags` liste les tags de votre application sur le réseau, avec `201` lorsque le tag a été ajouté et `200` lorsqu'il était déjà présent sur le réseau. Un tag appartenant à une autre application, ou qui n'existe pas, renvoie 404 `Tag not found.`. Nécessite une clé API avec accès complet, ou `write:networks` pour un membre de la console.",
        "operationId": "add_network_tag",
        "tags": [
          "Networks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            },
            "description": "UUID du réseau."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NetworkTagRequest"
              },
              "example": {
                "tag_uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/3fa85f64-5717-4562-b3fc-2c963f66afa6/tags/add/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"tag_uuid\": \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.networks.add_tag(\n    \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    tag_uuid=\"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.networks.addTag(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  tag_uuid: \"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Networks.AddTag(ctx, \"3fa85f64-5717-4562-b3fc-2c963f66afa6\", didit.NetworkTagRequest{\n\tTagUUID: \"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.NetworkTagRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.networks().addTag(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", NetworkTagRequest.builder()\n        .tagUuid(\"7c9e6679-7425-40de-944b-e07fc1f90ae7\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->networks->addTag('3fa85f64-5717-4562-b3fc-2c963f66afa6', [\n    'tag_uuid' => '7c9e6679-7425-40de-944b-e07fc1f90ae7',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.networks.add_tag(\n  \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  tag_uuid: \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.AddTagAsync(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", new NetworkTagRequest\n{\n    TagUuid = \"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "L'étiquette a été ajoutée. Renvoie les détails du réseau.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkDetailResponse"
                },
                "example": {
                  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "network_id": "N-0042",
                  "name": null,
                  "status": "in_review",
                  "risk": {
                    "score": 82,
                    "band": "high",
                    "bar": 0.82
                  },
                  "pattern_types": [
                    "exact_same_device",
                    "same_email"
                  ],
                  "signal_types": [
                    "device",
                    "email"
                  ],
                  "member_counts": {
                    "total": 3,
                    "users": 3,
                    "businesses": 0,
                    "transaction_parties": 0
                  },
                  "member_status": {
                    "approved": 1,
                    "declined": 1,
                    "in_review": 0,
                    "not_completed": 1
                  },
                  "signal_coverage": {
                    "device": {
                      "signals": 1,
                      "subjects": 3,
                      "coverage": 1.0
                    },
                    "email": {
                      "signals": 1,
                      "subjects": 2,
                      "coverage": 0.6667
                    }
                  },
                  "first_activity_at": "2026-10-01T09:12:44Z",
                  "last_activity_at": "2026-10-12T16:03:10Z",
                  "stats": {
                    "members": {
                      "total": 3,
                      "users": 3,
                      "businesses": 0,
                      "transaction_parties": 0
                    },
                    "member_status": {
                      "approved": 1,
                      "declined": 1,
                      "in_review": 0,
                      "not_completed": 1
                    },
                    "signals": {
                      "total": 2,
                      "by_type": {
                        "device": {
                          "signals": 1,
                          "subjects": 3,
                          "coverage": 1.0
                        },
                        "email": {
                          "signals": 1,
                          "subjects": 2,
                          "coverage": 0.6667
                        }
                      }
                    }
                  },
                  "fraud_tags": [],
                  "risk_signals": {
                    "residential_proxy_reuse": {
                      "detected": false,
                      "signal_count": 0,
                      "max_subject_count": 0
                    },
                    "email_intelligence": {
                      "enriched_signal_count": 1,
                      "high_risk_count": 0,
                      "social_profile_count": 0
                    },
                    "phone_intelligence": {
                      "enriched_signal_count": 0,
                      "high_risk_count": 0
                    }
                  },
                  "reviewed_at": "2026-10-12T16:30:00Z",
                  "reviewed_by": "reviewer@example.com",
                  "review_reason": "Shared device across three new accounts.",
                  "notes_count": 0,
                  "sharing_mode": "global",
                  "cross_org_available": true,
                  "cross_org_unavailable_reason": null,
                  "tags": [
                    {
                      "uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
                      "name": "SUSPICIOUS",
                      "color": "#6366F1",
                      "source": "custom",
                      "added_by": null,
                      "added_at": "2026-10-13T08:15:00Z"
                    }
                  ],
                  "outcomes": {
                    "approved": 1,
                    "declined": 1,
                    "in_review": 0,
                    "total": 3
                  },
                  "patterns": [
                    {
                      "type": "background",
                      "score": 0.8125,
                      "members": 3,
                      "reason": null,
                      "computed_at": "2026-10-13T08:00:00Z"
                    }
                  ]
                }
              }
            }
          },
          "200": {
            "description": "L'étiquette était déjà présente sur le réseau et est laissée telle quelle. Renvoie les détails du réseau.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkDetailResponse"
                },
                "example": {
                  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "network_id": "N-0042",
                  "name": null,
                  "status": "in_review",
                  "risk": {
                    "score": 82,
                    "band": "high",
                    "bar": 0.82
                  },
                  "pattern_types": [
                    "exact_same_device",
                    "same_email"
                  ],
                  "signal_types": [
                    "device",
                    "email"
                  ],
                  "member_counts": {
                    "total": 3,
                    "users": 3,
                    "businesses": 0,
                    "transaction_parties": 0
                  },
                  "member_status": {
                    "approved": 1,
                    "declined": 1,
                    "in_review": 0,
                    "not_completed": 1
                  },
                  "signal_coverage": {
                    "device": {
                      "signals": 1,
                      "subjects": 3,
                      "coverage": 1.0
                    },
                    "email": {
                      "signals": 1,
                      "subjects": 2,
                      "coverage": 0.6667
                    }
                  },
                  "first_activity_at": "2026-10-01T09:12:44Z",
                  "last_activity_at": "2026-10-12T16:03:10Z",
                  "stats": {
                    "members": {
                      "total": 3,
                      "users": 3,
                      "businesses": 0,
                      "transaction_parties": 0
                    },
                    "member_status": {
                      "approved": 1,
                      "declined": 1,
                      "in_review": 0,
                      "not_completed": 1
                    },
                    "signals": {
                      "total": 2,
                      "by_type": {
                        "device": {
                          "signals": 1,
                          "subjects": 3,
                          "coverage": 1.0
                        },
                        "email": {
                          "signals": 1,
                          "subjects": 2,
                          "coverage": 0.6667
                        }
                      }
                    }
                  },
                  "fraud_tags": [],
                  "risk_signals": {
                    "residential_proxy_reuse": {
                      "detected": false,
                      "signal_count": 0,
                      "max_subject_count": 0
                    },
                    "email_intelligence": {
                      "enriched_signal_count": 1,
                      "high_risk_count": 0,
                      "social_profile_count": 0
                    },
                    "phone_intelligence": {
                      "enriched_signal_count": 0,
                      "high_risk_count": 0
                    }
                  },
                  "reviewed_at": "2026-10-12T16:30:00Z",
                  "reviewed_by": "reviewer@example.com",
                  "review_reason": "Shared device across three new accounts.",
                  "notes_count": 0,
                  "sharing_mode": "global",
                  "cross_org_available": true,
                  "cross_org_unavailable_reason": null,
                  "tags": [
                    {
                      "uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
                      "name": "SUSPICIOUS",
                      "color": "#6366F1",
                      "source": "custom",
                      "added_by": null,
                      "added_at": "2026-10-13T08:15:00Z"
                    }
                  ],
                  "outcomes": {
                    "approved": 1,
                    "declined": 1,
                    "in_review": 0,
                    "total": 3
                  },
                  "patterns": [
                    {
                      "type": "background",
                      "score": 0.8125,
                      "members": 3,
                      "reason": null,
                      "computed_at": "2026-10-13T08:00:00Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide : `tag_uuid` est manquant ou n'est pas un UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tag_uuid": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "Missing tag_uuid": {
                    "summary": "tag_uuid manquant",
                    "value": {
                      "tag_uuid": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid tag_uuid": {
                    "summary": "tag_uuid non valide",
                    "value": {
                      "tag_uuid": [
                        "Must be a valid UUID."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Identifiants manquants ou invalides.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Identifiants manquants ou invalides",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé API appartient à une autre application, ou il s'agit d'une clé avec un accès restreint : les endpoints Networks nécessitent une clé avec accès complet. Un token de membre de la console nécessite `write:networks`. Renvoyé également avec `code: networks_not_entitled` lorsque Networks n'est pas activé pour l'organisation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Networks not enabled": {
                    "summary": "Réseaux non activés",
                    "value": {
                      "detail": "Networks is disabled for this organization. Contact Didit support if you believe this is an error.",
                      "code": "networks_not_entitled"
                    }
                  },
                  "Restricted API key": {
                    "summary": "Clé API restreinte",
                    "value": {
                      "detail": "This API key has no access to this endpoint."
                    }
                  },
                  "No permission": {
                    "summary": "Aucune autorisation",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Introuvable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Network not found": {
                    "summary": "Réseau non trouvé",
                    "value": {
                      "detail": "Network not found."
                    }
                  },
                  "Tag not found": {
                    "summary": "Tag introuvable",
                    "value": {
                      "detail": "Tag not found."
                    }
                  }
                }
              }
            }
          }
        },
        "x-didit-sdk": {
          "resource": "networks",
          "method": "add_tag",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        }
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/networks/{network_uuid}/tags/remove/": {
      "post": {
        "summary": "Retirer un tag d'un réseau",
        "description": "Retire l'un des tags de votre application du réseau. Renvoie les détails du réseau. Renvoie 404 lorsque le tag ne figure pas sur le réseau ou n'appartient pas à votre application. Nécessite une clé API avec accès complet ou `write:networks` pour un membre de la console.",
        "operationId": "remove_network_tag",
        "tags": [
          "Networks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          },
          {
            "name": "network_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            },
            "description": "UUID du réseau."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NetworkTagRequest"
              },
              "example": {
                "tag_uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/networks/3fa85f64-5717-4562-b3fc-2c963f66afa6/tags/remove/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"tag_uuid\": \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.networks.remove_tag(\n    \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    tag_uuid=\"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.networks.removeTag(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  tag_uuid: \"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Networks.RemoveTag(ctx, \"3fa85f64-5717-4562-b3fc-2c963f66afa6\", didit.NetworkTagRequest{\n\tTagUUID: \"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.NetworkTagRequest;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.networks().removeTag(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", NetworkTagRequest.builder()\n        .tagUuid(\"7c9e6679-7425-40de-944b-e07fc1f90ae7\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->networks->removeTag('3fa85f64-5717-4562-b3fc-2c963f66afa6', [\n    'tag_uuid' => '7c9e6679-7425-40de-944b-e07fc1f90ae7',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.networks.remove_tag(\n  \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  tag_uuid: \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Networks.RemoveTagAsync(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", new NetworkTagRequest\n{\n    TagUuid = \"7c9e6679-7425-40de-944b-e07fc1f90ae7\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'étiquette a été retirée du réseau. Renvoie les détails du réseau.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkDetailResponse"
                },
                "example": {
                  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "network_id": "N-0042",
                  "name": null,
                  "status": "in_review",
                  "risk": {
                    "score": 82,
                    "band": "high",
                    "bar": 0.82
                  },
                  "pattern_types": [
                    "exact_same_device",
                    "same_email"
                  ],
                  "signal_types": [
                    "device",
                    "email"
                  ],
                  "member_counts": {
                    "total": 3,
                    "users": 3,
                    "businesses": 0,
                    "transaction_parties": 0
                  },
                  "member_status": {
                    "approved": 1,
                    "declined": 1,
                    "in_review": 0,
                    "not_completed": 1
                  },
                  "signal_coverage": {
                    "device": {
                      "signals": 1,
                      "subjects": 3,
                      "coverage": 1.0
                    },
                    "email": {
                      "signals": 1,
                      "subjects": 2,
                      "coverage": 0.6667
                    }
                  },
                  "first_activity_at": "2026-10-01T09:12:44Z",
                  "last_activity_at": "2026-10-12T16:03:10Z",
                  "stats": {
                    "members": {
                      "total": 3,
                      "users": 3,
                      "businesses": 0,
                      "transaction_parties": 0
                    },
                    "member_status": {
                      "approved": 1,
                      "declined": 1,
                      "in_review": 0,
                      "not_completed": 1
                    },
                    "signals": {
                      "total": 2,
                      "by_type": {
                        "device": {
                          "signals": 1,
                          "subjects": 3,
                          "coverage": 1.0
                        },
                        "email": {
                          "signals": 1,
                          "subjects": 2,
                          "coverage": 0.6667
                        }
                      }
                    }
                  },
                  "fraud_tags": [],
                  "risk_signals": {
                    "residential_proxy_reuse": {
                      "detected": false,
                      "signal_count": 0,
                      "max_subject_count": 0
                    },
                    "email_intelligence": {
                      "enriched_signal_count": 1,
                      "high_risk_count": 0,
                      "social_profile_count": 0
                    },
                    "phone_intelligence": {
                      "enriched_signal_count": 0,
                      "high_risk_count": 0
                    }
                  },
                  "reviewed_at": "2026-10-12T16:30:00Z",
                  "reviewed_by": "reviewer@example.com",
                  "review_reason": "Shared device across three new accounts.",
                  "notes_count": 0,
                  "sharing_mode": "global",
                  "cross_org_available": true,
                  "cross_org_unavailable_reason": null,
                  "tags": [],
                  "outcomes": {
                    "approved": 1,
                    "declined": 1,
                    "in_review": 0,
                    "total": 3
                  },
                  "patterns": [
                    {
                      "type": "background",
                      "score": 0.8125,
                      "members": 3,
                      "reason": null,
                      "computed_at": "2026-10-13T08:00:00Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide : `tag_uuid` est manquant ou n'est pas un UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tag_uuid": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "Missing tag_uuid": {
                    "summary": "tag_uuid manquant",
                    "value": {
                      "tag_uuid": [
                        "This field is required."
                      ]
                    }
                  },
                  "Invalid tag_uuid": {
                    "summary": "tag_uuid non valide",
                    "value": {
                      "tag_uuid": [
                        "Must be a valid UUID."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Identifiants manquants ou invalides.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Identifiants manquants ou invalides",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La clé API appartient à une autre application, ou il s'agit d'une clé avec un accès restreint : les endpoints Networks nécessitent une clé avec accès complet. Un token de membre de la console nécessite `write:networks`. Renvoyé également avec `code: networks_not_entitled` lorsque Networks n'est pas activé pour l'organisation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Networks not enabled": {
                    "summary": "Réseaux non activés",
                    "value": {
                      "detail": "Networks is disabled for this organization. Contact Didit support if you believe this is an error.",
                      "code": "networks_not_entitled"
                    }
                  },
                  "Restricted API key": {
                    "summary": "Clé API restreinte",
                    "value": {
                      "detail": "This API key has no access to this endpoint."
                    }
                  },
                  "No permission": {
                    "summary": "Aucune autorisation",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Introuvable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "description": "Présent sur les erreurs codées, par exemple `networks_not_entitled`."
                    }
                  }
                },
                "examples": {
                  "Network not found": {
                    "summary": "Réseau non trouvé",
                    "value": {
                      "detail": "Network not found."
                    }
                  },
                  "Tag not found": {
                    "summary": "Tag introuvable",
                    "value": {
                      "detail": "Tag not found."
                    }
                  },
                  "Tag not on the network": {
                    "summary": "Tag absent du réseau",
                    "value": {
                      "detail": "This tag is not on the network."
                    }
                  }
                }
              }
            }
          }
        },
        "x-didit-sdk": {
          "resource": "networks",
          "method": "remove_tag",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        }
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/cases/{case_uuid}/requests/{request_uuid}/remind/": {
      "post": {
        "summary": "Relancer le client au sujet d'une requête",
        "description": "Renvoyez l'e-mail d'une demande client en attente, au même destinataire vérifié, avec le même contenu. Vous pouvez relancer une demande au maximum une fois toutes les 24 heures. Une relance ne modifie rien d'autre : la demande conserve son échéance et le dossier conserve son statut. Chaque relance est consignée dans le dossier sous forme d'événement CUSTOMER_REQUEST avec l'action `reminded`. Le champ `delivery_status` de la réponse indique comment la livraison de cette relance s'est terminée : SENT, SIMULATED (l'e-mail n'a pas été envoyé) ou UNKNOWN (l'e-mail a pu être accepté ; il n'est pas renvoyé automatiquement). `next_reminder_at` indique le moment où vous pourrez relancer cette demande. Renvoie 409 avec une `reason` lorsque le client n'a plus à répondre à la demande, et 429 avec `retry_at` et un en-tête `Retry-After` lorsque la demande a déjà été relancée au cours des dernières 24 heures. Nécessite `write:cases`.",
        "operationId": "organization_application_cases_requests_remind_create",
        "parameters": [
          {
            "in": "path",
            "name": "organization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "description": "UUID de l'organisation."
          },
          {
            "in": "path",
            "name": "application_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "description": "UUID de l'application."
          },
          {
            "in": "path",
            "name": "case_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "description": "UUID du dossier."
          },
          {
            "in": "path",
            "name": "request_uuid",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "description": "UUID de requête client, issu de la liste des requêtes du dossier."
          }
        ],
        "tags": [
          "Case Management"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/cases/c1a5e000-0000-4000-8000-000000000001/requests/3fa85f64-5717-4562-b3fc-2c963f66afa6/remind/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nresult = client.cases.requests.remind(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nconst result = await didit.cases.requests.remind(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nclient := didit.NewClient()\n\nresult, err := client.Cases.Requests.Remind(ctx, \"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nvar result = client.cases().requests().remind(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$result = $didit->cases->requests->remind('11111111-2222-3333-4444-555555555555', '11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\nresult = didit.cases.requests.remind(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"11111111-2222-3333-4444-555555555555\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nvar result = await client.Cases.Requests.RemindAsync(\"11111111-2222-3333-4444-555555555555\", \"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le rappel a été enregistré et son e-mail envoyé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "request",
                    "reminded_at",
                    "delivery_status",
                    "next_reminder_at"
                  ],
                  "properties": {
                    "request": {
                      "$ref": "#/components/schemas/CustomerMessagingCaseRequest"
                    },
                    "reminded_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Date et heure auxquelles ce rappel a été enregistré."
                    },
                    "delivery_status": {
                      "type": "string",
                      "enum": [
                        "SENT",
                        "SIMULATED",
                        "UNKNOWN"
                      ],
                      "description": "Manière dont la livraison de ce rappel s'est terminée. SIMULATED : l'e-mail n'a pas été envoyé. UNKNOWN : l'e-mail a peut-être été accepté ; il n'est pas renvoyé automatiquement."
                    },
                    "next_reminder_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Date et heure à partir desquelles vous pouvez relancer cette requête : `reminded_at` plus 24 heures."
                    }
                  }
                },
                "example": {
                  "request": {
                    "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "purpose": "confirm_details",
                    "language": "en",
                    "recipient": "customer@example.com",
                    "expires_at": "2026-10-20T09:00:00Z",
                    "actor_email": "reviewer@example.com",
                    "delivery_status": "SENT",
                    "delivered_at": "2026-10-13T09:00:04Z",
                    "cancelled_at": null,
                    "responded_at": null,
                    "response": null,
                    "has_attachment": false,
                    "created_at": "2026-10-13T09:00:00Z"
                  },
                  "reminded_at": "2026-10-14T10:30:00Z",
                  "delivery_status": "SENT",
                  "next_reminder_at": "2026-10-15T10:30:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Le dossier a une résolution en attente d'approbation. Le corps est une liste de chaînes de caractères.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "example": [
                  "Customer messages require an active case without a pending resolution."
                ]
              }
            }
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les dossiers."
          },
          "404": {
            "description": "La requête ou le dossier n'est pas disponible pour cet appelant."
          },
          "409": {
            "description": "La requête n'est plus en attente du client, il n'y a donc rien à lui rappeler. `reason` en indique la cause : `answered` (le client a répondu), `cancelled`, `expired`, `closed` (le dossier a été résolu après l'envoi de la requête, même s'il a été rouvert depuis), `not_actionable` (une mise à jour avec examen en cours ne demande rien), `not_delivered` (le premier e-mail n'a pas été envoyé), ou `contact_unavailable` (l'e-mail vérifié n'est plus disponible).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "case_request_not_waiting"
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "answered",
                        "cancelled",
                        "expired",
                        "closed",
                        "not_actionable",
                        "not_delivered",
                        "contact_unavailable"
                      ]
                    }
                  }
                },
                "example": {
                  "detail": "This request no longer waits on the customer, so there is nothing to remind them of.",
                  "code": "case_request_not_waiting",
                  "reason": "answered"
                }
              }
            }
          },
          "429": {
            "description": "La requête a déjà fait l'objet d'une relance au cours des dernières 24 heures. `retry_at` et l'en-tête `Retry-After` indiquent quand vous pouvez la relancer à nouveau.",
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de pouvoir relancer cette requête.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 3600
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "case_request_reminder_too_soon"
                      ]
                    },
                    "retry_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "detail": "This request was already reminded in the last 24 hours.",
                  "code": "case_request_reminder_too_soon",
                  "retry_at": "2026-10-15T10:30:00Z"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-didit-sdk": {
          "resource": "cases.requests",
          "method": "remind",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        }
      }
    },
    "/v3/session/{sessionId}/decision-email-preview/": {
      "post": {
        "summary": "Prévisualiser l'e-mail de décision d'une session",
        "description": "Générez un aperçu de l'e-mail que la personne reçoit lorsque vous faites passer une session à `Approved` ou `Declined` avec `send_email: true`, sans modifier la session ni envoyer quoi que ce soit. La réponse affiche l'objet et le code HTML exactement tels qu'ils sont envoyés, le destinataire, l'expéditeur, la langue, et indique si la confirmation du changement déclenche réellement l'envoi de l'e-mail (`will_be_sent`, `not_sent_reason`).\n\nLe destinataire est la propre adresse de la personne : celle qu'elle a vérifiée lors d'une étape de vérification de l'e-mail du flux, ou à défaut celle fournie dans `contact_details` lors de la création de la session. L'expéditeur correspond au domaine d'expéditeur vérifié de votre application si la marque blanche s'applique (`sender_kind: customer`), sinon il s'agit de l'expéditeur de Didit (`sender_kind: didit`).\n\nPour envoyer exactement ce que vous avez prévisualisé, appelez [Update Session Status](/fr/sessions-api/update-status) avec le même `new_status`, `send_email: true`, `email_address` défini sur `recipient`, `email_language` défini sur `language` et `email_preview_token` défini sur `preview_token`. Le reçu expire au bout de 15 minutes. Si le destinataire, la langue, le statut de la session, l'expéditeur ou l'e-mail a changé depuis l'aperçu, la mise à jour renvoie `409` avant toute modification ; générez un nouvel aperçu et confirmez avec le nouveau reçu.\n\nFonctionne pour les sessions de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB) dont le statut est `Approved`, `Declined`, `In Review`, `Kyc Expired`, `Abandoned` ou `Resubmitted`. La vérification du statut intervient avant la validation du corps de requête. Nécessite le privilège `write:sessions` ; une clé API restreinte nécessite un accès en écriture aux décisions. Les réponses utilisent `Cache-Control: no-store` : traitez-les comme du contenu de vérification sensible.",
        "operationId": "post_v3_session_decision_email_preview",
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sessionId",
            "required": true,
            "description": "UUID de la session de vérification. Accepte les identifiants de session d'utilisateur (KYC) et d'entreprise (KYB).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "new_status"
                ],
                "properties": {
                  "new_status": {
                    "type": "string",
                    "enum": [
                      "Approved",
                      "Declined"
                    ],
                    "description": "La décision dont vous souhaitez prévisualiser l'e-mail.",
                    "example": "Approved"
                  },
                  "email_language": {
                    "type": "string",
                    "default": "en",
                    "description": "Langue de l'e-mail, même valeur par défaut que pour Update Session Status. Une langue non proposée bascule sur l'anglais ; `language` dans la réponse indique celle qui est utilisée.",
                    "example": "en"
                  }
                }
              },
              "examples": {
                "Approved": {
                  "summary": "Prévisualiser l'e-mail Approuvé en anglais",
                  "value": {
                    "new_status": "Approved"
                  }
                },
                "Declined in Spanish": {
                  "summary": "Prévisualiser l'e-mail Refusé en espagnol",
                  "value": {
                    "new_status": "Declined",
                    "email_language": "es"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Prévisualisation uniquement. La session reste inchangée et aucun e-mail n'est envoyé.",
            "headers": {
              "Cache-Control": {
                "description": "Toujours `no-store` : l'aperçu contient du contenu de vérification et ne doit pas être mis en cache.",
                "schema": {
                  "type": "string",
                  "example": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "recipient",
                    "recipient_source",
                    "sender",
                    "sender_name",
                    "sender_email",
                    "sender_kind",
                    "subject",
                    "html",
                    "text",
                    "language",
                    "will_be_sent",
                    "not_sent_reason",
                    "preview_token"
                  ],
                  "properties": {
                    "recipient": {
                      "type": "string",
                      "description": "L'adresse à laquelle l'e-mail est envoyé. Une chaîne vide lorsqu'aucune adresse n'est connue pour la personne : aucun e-mail ne peut alors être envoyé et `preview_token` est également vide. Transmettez-la en tant que `email_address` lors de la confirmation.",
                      "example": "person@example.com"
                    },
                    "recipient_source": {
                      "type": "string",
                      "enum": [
                        "email_verification",
                        "contact_details",
                        ""
                      ],
                      "description": "Provenance de `recipient`. `email_verification` : l'adresse vérifiée par la personne lors d'une étape de vérification de l'e-mail du flux. `contact_details` : l'adresse fournie dans `contact_details` lors de la création de la session. Une chaîne vide lorsqu'il n'y a pas d'adresse.",
                      "example": "email_verification"
                    },
                    "sender": {
                      "type": "string",
                      "description": "L'en-tête `From` avec lequel l'e-mail est envoyé.",
                      "example": "Example App <no-reply@mail.example.com>"
                    },
                    "sender_name": {
                      "type": "string",
                      "description": "La partie nom d'affichage de `sender`.",
                      "example": "Example App"
                    },
                    "sender_email": {
                      "type": "string",
                      "format": "email",
                      "description": "La partie adresse de `sender`.",
                      "example": "no-reply@mail.example.com"
                    },
                    "sender_kind": {
                      "type": "string",
                      "enum": [
                        "customer",
                        "didit"
                      ],
                      "description": "`customer` : l'e-mail est envoyé depuis le domaine d'expéditeur vérifié de votre application (marque blanche). `didit` : il est envoyé depuis le propre expéditeur de Didit.",
                      "example": "customer"
                    },
                    "subject": {
                      "type": "string",
                      "description": "La ligne d'objet exactement telle qu'elle est envoyée.",
                      "example": "Your verification has been approved in Example App"
                    },
                    "html": {
                      "type": "string",
                      "description": "Le HTML de l'e-mail exactement tel qu'il est envoyé, avec son logo intégré sous forme de data URL. Affichez-le dans un cadre sandboxé, jamais directement dans le DOM de votre application.",
                      "example": "<!DOCTYPE html><html><body>...</body></html>"
                    },
                    "text": {
                      "type": "string",
                      "description": "Le texte brut de l'e-mail, tel qu'il apparaît dans le fil Messages de la personne, pour un aperçu compact (le HTML reste l'e-mail que la personne reçoit).",
                      "example": "Verification Approved\n\nYour identity has been successfully verified with Acme Pay. No further action is needed on your part."
                    },
                    "language": {
                      "type": "string",
                      "description": "La langue dans laquelle l'e-mail est rédigé. Anglais (`en`) lorsque le `email_language` demandé n'est pas proposé.",
                      "example": "en"
                    },
                    "will_be_sent": {
                      "type": "boolean",
                      "description": "Indique si la confirmation de la modification avec `send_email: true` envoie cet e-mail. `false` lorsque `not_sent_reason` est défini.",
                      "example": true
                    },
                    "not_sent_reason": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "status_unchanged",
                        "notification_emails_disabled",
                        "no_recipient",
                        "sandbox",
                        null
                      ],
                      "description": "Raison pour laquelle la confirmation n'enverrait aucun e-mail, ou `null` lorsqu'il sera envoyé. `status_unchanged` : la session possède déjà ce statut, la mise à jour ne change donc rien et n'envoie rien. `notification_emails_disabled` : la session a été créée sans `contact_details.send_notification_emails: true`, donc aucun e-mail de décision n'est envoyé à l'adresse fournie dans `contact_details`. `no_recipient` : aucune adresse n'est connue pour la personne. `sandbox` : une session sandbox dont le destinataire n'a pas accepté la réception d'e-mails en sandbox, l'envoi est donc seulement simulé.",
                      "example": null
                    },
                    "preview_token": {
                      "type": "string",
                      "description": "Récépissé signé pour cet e-mail exact, valide pendant 15 minutes. Transmettez-le en tant que `email_preview_token` à [Mettre à jour le statut de la session](/fr/sessions-api/update-status). Une chaîne vide lorsqu'il n'y a aucun destinataire.",
                      "example": "eyJkaWdlc3QiOiI0ZjJhIn0:1uExAm:Pl3x4mpleS1gnatureValue000000000000000"
                    }
                  }
                },
                "examples": {
                  "Will Be Sent": {
                    "summary": "L'e-mail Approuvé est envoyé à l'adresse vérifiée dans le flux",
                    "value": {
                      "recipient": "person@example.com",
                      "recipient_source": "email_verification",
                      "sender": "Example App <no-reply@mail.example.com>",
                      "sender_name": "Example App",
                      "sender_email": "no-reply@mail.example.com",
                      "sender_kind": "customer",
                      "subject": "Your verification has been approved in Example App",
                      "html": "<!DOCTYPE html><html><body>...</body></html>",
                      "language": "en",
                      "will_be_sent": true,
                      "not_sent_reason": null,
                      "preview_token": "eyJkaWdlc3QiOiI0ZjJhIn0:1uExAm:Pl3x4mpleS1gnatureValue000000000000000"
                    }
                  },
                  "No Recipient": {
                    "summary": "Aucune adresse n'est connue pour cette personne",
                    "value": {
                      "recipient": "",
                      "recipient_source": "",
                      "sender": "Example App <no-reply@mail.example.com>",
                      "sender_name": "Example App",
                      "sender_email": "no-reply@mail.example.com",
                      "sender_kind": "customer",
                      "subject": "Your verification has been declined in Example App",
                      "html": "<!DOCTYPE html><html><body>...</body></html>",
                      "language": "en",
                      "will_be_sent": false,
                      "not_sent_reason": "no_recipient",
                      "preview_token": ""
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "La session n'est pas dans un statut accepté par cet endpoint (`{\"detail\": ...}`), ou le corps est invalide (`{\"<field>\": [\"<message>\"]}`).",
            "content": {
              "application/json": {
                "examples": {
                  "Wrong Current Status": {
                    "summary": "La session n'est pas dans un statut accepté par cet endpoint",
                    "value": {
                      "detail": "Only sessions with status Approved, Declined, In Review, Kyc Expired, Abandoned, Resubmitted can be updated. Current status: In Progress"
                    }
                  },
                  "Invalid new_status": {
                    "summary": "new_status n'est ni Approved ni Declined",
                    "value": {
                      "new_status": [
                        "\"Resubmitted\" is not a valid choice."
                      ]
                    }
                  },
                  "Missing new_status": {
                    "summary": "Champ obligatoire omis",
                    "value": {
                      "new_status": [
                        "This field is required."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré.",
            "content": {
              "application/json": {
                "examples": {
                  "Expired API Key": {
                    "summary": "Clé API restreinte ayant dépassé sa date d'expiration",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Identifiants manquants, appelant sans le privilège `write:sessions`, clé API avec restriction de portée ne disposant pas de l'accès requis par cet endpoint, ou un `session_id` qui appartient à une autre application.",
            "content": {
              "application/json": {
                "examples": {
                  "Invalid Credentials": {
                    "summary": "x-api-key manquant ou invalide",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Missing Privilege": {
                    "summary": "L'appelant n'a pas write:sessions",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped Key Without Access": {
                    "summary": "Clé API restreinte sans cet accès",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Aucune session KYC ou KYB avec ce `session_id` n'existe.",
            "content": {
              "application/json": {
                "examples": {
                  "Not Found": {
                    "summary": "session_id inconnu",
                    "value": {
                      "detail": "Not found."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST \\\n  https://verification.didit.me/v3/session/3fa85f64-5717-4562-b3fc-2c963f66afa6/decision-email-preview/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"new_status\": \"Approved\", \"email_language\": \"en\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.preview_decision_email(\n    \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    new_status=\"Approved\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.previewDecisionEmail(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  new_status: \"Approved\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.PreviewDecisionEmail(ctx, \"3fa85f64-5717-4562-b3fc-2c963f66afa6\", didit.SessionsPreviewDecisionEmailParams{\n\tNewStatus: \"Approved\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsPreviewDecisionEmailParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().previewDecisionEmail(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", SessionsPreviewDecisionEmailParams.builder()\n        .newStatus(SessionsPreviewDecisionEmailParams.NewStatus.of(\"Approved\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->previewDecisionEmail('3fa85f64-5717-4562-b3fc-2c963f66afa6', [\n    'new_status' => 'Approved',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.preview_decision_email(\n  \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  new_status: \"Approved\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.PreviewDecisionEmailAsync(\"3fa85f64-5717-4562-b3fc-2c963f66afa6\", new SessionsPreviewDecisionEmailParams\n{\n    NewStatus = \"Approved\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "preview_decision_email",
          "auth": "api_key",
          "server": true
        }
      }
    },
    "/v3/travel-rule/join/{token}/": {
      "get": {
        "summary": "Obtenir une invitation à rejoindre gratuitement",
        "description": "Public, non authentifié. Affiche l'invitation à laquelle correspond un lien d'adhésion tant qu'elle est ouverte : qui l'a demandée, l'adresse à laquelle elle a été envoyée et les valeurs de l'annuaire qui seront préremplies. Le token sert d'authentification.",
        "operationId": "getTravelRuleJoinInvitation",
        "x-didit-sdk": {
          "resource": "travel_rule.join",
          "method": "get_invitation",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Le token d'invitation issu du lien pour rejoindre."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://verification.didit.me/v3/travel-rule/join/{token}/"
          }
        ],
        "responses": {
          "200": {
            "description": "L'invitation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleJoinInvitation"
                }
              }
            }
          },
          "404": {
            "description": "Aucune invitation ne correspond à ce lien."
          },
          "410": {
            "description": "L'invitation n'est plus ouverte : expirée, déjà utilisée ou retirée."
          }
        }
      },
      "post": {
        "summary": "Créer un compte Travel Rule gratuit",
        "description": "Public, non authentifié. Crée un compte Travel Rule gratuit pour un VASP contrepartie ayant reçu une requête. L'e-mail doit être l'adresse à laquelle l'invitation a été envoyée. Un code à 6 caractères y est envoyé ; transmettez-le à l'endpoint de vérification pour terminer. Les tentatives d'inscription font l'objet d'une limite de débit par adresse et par IP.",
        "operationId": "registerTravelRuleJoin",
        "x-didit-sdk": {
          "resource": "travel_rule.join",
          "method": "register",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Le token d'invitation issu du lien pour rejoindre."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleJoinRegisterRequest"
              },
              "example": {
                "email": "compliance@example.com",
                "password": "a-long-passphrase"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/join/{token}/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"email\": \"compliance@example.com\", \"password\": \"a-long-passphrase\"}'"
          }
        ],
        "responses": {
          "202": {
            "description": "Le compte a été créé et un code a été envoyé par e-mail.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Indique à la contrepartie de vérifier sa boîte e-mail pour trouver le code de vérification."
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "description": "L'adresse à laquelle le code a été envoyé."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "L'adresse e-mail n'est pas l'adresse invitée, ou le mot de passe ou l'adresse ont été refusés."
          },
          "404": {
            "description": "Aucune invitation ne correspond à ce lien."
          },
          "410": {
            "description": "L'invitation n'est plus ouverte : expirée, déjà utilisée ou retirée."
          },
          "429": {
            "description": "Trop de tentatives pour rejoindre. Les en-têtes `X-RateLimit-*` indiquent le quota consommé."
          }
        }
      }
    },
    "/v3/travel-rule/join/{token}/verify/": {
      "post": {
        "summary": "Vérifier un compte Travel Rule gratuit",
        "description": "Public, non authentifié. Consomme le code envoyé par e-mail, crée l'organisation gratuite et renvoie les identifiants que son application utilise sur les endpoints de l'espace de travail. La réception de données Travel Rule est gratuite.",
        "operationId": "verifyTravelRuleJoin",
        "x-didit-sdk": {
          "resource": "travel_rule.join",
          "method": "verify",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Le token d'invitation issu du lien pour rejoindre."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleJoinVerifyRequest"
              },
              "example": {
                "email": "compliance@example.com",
                "code": "123456"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/join/{token}/verify/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"email\": \"compliance@example.com\", \"code\": \"123456\"}'"
          }
        ],
        "responses": {
          "201": {
            "description": "Les identifiants de l'organisation et de l'application.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleJoinCredentials"
                }
              }
            }
          },
          "400": {
            "description": "Le code ou l'e-mail a été refusé."
          },
          "404": {
            "description": "Aucune invitation ne correspond à ce lien."
          },
          "410": {
            "description": "L'invitation n'est plus ouverte : expirée, déjà utilisée ou retirée."
          },
          "429": {
            "description": "Trop de tentatives pour rejoindre. Les en-têtes `X-RateLimit-*` indiquent le quota consommé."
          }
        }
      }
    },
    "/v3/travel-rule/workspace/": {
      "get": {
        "summary": "Obtenir l'espace de travail Travel Rule gratuit",
        "description": "Lit l'espace de travail gratuit d'une application ayant souscrit gratuitement : revendication dans l'annuaire, preuve de domaine, facturation et inscription au réseau Didit.",
        "operationId": "getTravelRuleWorkspace",
        "x-didit-sdk": {
          "resource": "travel_rule.workspace",
          "method": "get",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/workspace/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.workspace.get()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.workspace.get();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.Workspace.Get(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().workspace().get();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->workspace->get();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.workspace.get\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Workspace.GetAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'espace de travail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWorkspace"
                }
              }
            }
          },
          "404": {
            "description": "Cette application n'a pas rejoint avec l'offre gratuite, elle ne dispose donc d'aucun espace de travail gratuit."
          }
        }
      }
    },
    "/v3/travel-rule/workspace/claim/": {
      "post": {
        "summary": "Revendiquer une entrée de l'annuaire",
        "description": "Revendique l'entrée de l'annuaire correspondant à cet espace de travail. Lorsque l'e-mail professionnel appartient à un domaine répertorié par l'entrée, la revendication est prouvée et s'applique immédiatement : le profil VASP et les paramètres Travel Rule sont renseignés à partir de l'entrée et la Travel Rule est activée, de sorte que le prochain transfert vers celle-ci transite par le réseau Didit. Sinon, la revendication reste en attente d'examen (`pending_review`).",
        "operationId": "claimTravelRuleWorkspace",
        "x-didit-sdk": {
          "resource": "travel_rule.workspace",
          "method": "claim",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleWorkspaceClaimRequest"
              },
              "example": {
                "vasp_id": "0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/workspace/claim/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"vasp_id\": \"0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.workspace.claim(\n    vasp_id=\"0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.workspace.claim({\n  vasp_id: \"0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.Workspace.Claim(ctx, didit.TravelRuleWorkspaceClaimRequest{\n\tVASPID: \"0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleWorkspaceClaimRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().workspace().claim(TravelRuleWorkspaceClaimRequest.builder()\n        .vaspId(\"0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->workspace->claim([\n    'vasp_id' => '0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.workspace.claim(vasp_id: \"0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Workspace.ClaimAsync(new TravelRuleWorkspaceClaimRequest\n{\n    VaspId = \"0b0c9d3e-5a53-4a3e-9d6e-1f2f6f6a1c11\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'espace de travail avec son statut de revendication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWorkspace"
                }
              }
            }
          },
          "400": {
            "description": "Aucune entrée d'annuaire ne possède cet identifiant."
          },
          "404": {
            "description": "Cette application n'a pas rejoint avec l'offre gratuite, elle ne dispose donc d'aucun espace de travail gratuit."
          }
        }
      }
    },
    "/v3/travel-rule/workspace/domain/code/": {
      "post": {
        "summary": "Envoyer un code de vérification de domaine par e-mail",
        "description": "Envoie un code à usage unique par e-mail à l'adresse professionnelle de l'espace de travail pour prouver qu'il contrôle le domaine de messagerie. Limité en débit, et un nombre restreint de tentatives erronées est accepté par code. Renvoie également l'enregistrement TXT pour l'alternative DNS.",
        "operationId": "sendTravelRuleWorkspaceDomainCode",
        "x-didit-sdk": {
          "resource": "travel_rule.workspace",
          "method": "send_domain_code",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/workspace/domain/code/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.workspace.send_domain_code()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.workspace.sendDomainCode();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.Workspace.SendDomainCode(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().workspace().sendDomainCode();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->workspace->sendDomainCode();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.workspace.send_domain_code\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Workspace.SendDomainCodeAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le domaine, son état et l'enregistrement TXT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWorkspaceDomainCodeResponse"
                }
              }
            }
          },
          "404": {
            "description": "Cette application n'a pas rejoint avec l'offre gratuite, elle ne dispose donc d'aucun espace de travail gratuit."
          }
        }
      }
    },
    "/v3/travel-rule/workspace/domain/confirm/": {
      "post": {
        "summary": "Confirmer le code de vérification du domaine",
        "description": "Consomme le code envoyé par e-mail et marque le domaine de l'e-mail comme vérifié.",
        "operationId": "confirmTravelRuleWorkspaceDomain",
        "x-didit-sdk": {
          "resource": "travel_rule.workspace",
          "method": "confirm_domain",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleWorkspaceDomainConfirmRequest"
              },
              "example": {
                "code": "123456"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/workspace/domain/confirm/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"code\": \"123456\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.workspace.confirm_domain(\n    code=\"123456\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.workspace.confirmDomain({\n  code: \"123456\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.Workspace.ConfirmDomain(ctx, didit.TravelRuleWorkspaceDomainConfirmRequest{\n\tCode: \"123456\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleWorkspaceDomainConfirmRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().workspace().confirmDomain(TravelRuleWorkspaceDomainConfirmRequest.builder()\n        .code(\"123456\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->workspace->confirmDomain([\n    'code' => '123456',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.workspace.confirm_domain(code: \"123456\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Workspace.ConfirmDomainAsync(new TravelRuleWorkspaceDomainConfirmRequest\n{\n    Code = \"123456\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'espace de travail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWorkspace"
                }
              }
            }
          },
          "400": {
            "description": "Le code est incorrect, expiré ou a déjà été utilisé."
          },
          "404": {
            "description": "Cette application n'a pas rejoint avec l'offre gratuite, elle ne dispose donc d'aucun espace de travail gratuit."
          }
        }
      }
    },
    "/v3/travel-rule/workspace/domain/dns/": {
      "post": {
        "summary": "Vérifier le domaine à partir de son enregistrement TXT",
        "description": "Vérifie la présence de l'enregistrement TXT `didit-tr-verify.<domain>` renvoyé par l'endpoint de code et marque le domaine comme vérifié lorsqu'il correspond. L'une des deux preuves, le code envoyé par e-mail ou l'enregistrement TXT, suffit.",
        "operationId": "verifyTravelRuleWorkspaceDomainDns",
        "x-didit-sdk": {
          "resource": "travel_rule.workspace",
          "method": "verify_domain_dns",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/workspace/domain/dns/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.workspace.verify_domain_dns()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.workspace.verifyDomainDns();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.Workspace.VerifyDomainDNS(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().workspace().verifyDomainDns();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->workspace->verifyDomainDns();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.workspace.verify_domain_dns\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Workspace.VerifyDomainDnsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'espace de travail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWorkspace"
                }
              }
            }
          },
          "400": {
            "description": "L'enregistrement TXT est introuvable ou ne correspond pas."
          },
          "404": {
            "description": "Cette application n'a pas rejoint avec l'offre gratuite, elle ne dispose donc d'aucun espace de travail gratuit."
          }
        }
      }
    },
    "/v3/travel-rule/workspace/billing/": {
      "post": {
        "summary": "Activer la facturation sortante",
        "description": "Active la facturation Travel Rule pour les transferts sortants de l'espace de travail. La réception reste gratuite. Cela ne peut pas être désactivé via l'API : contactez le support Didit.",
        "operationId": "enableTravelRuleWorkspaceBilling",
        "x-didit-sdk": {
          "resource": "travel_rule.workspace",
          "method": "enable_billing",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleWorkspaceBillingRequest"
              },
              "example": {
                "enabled": true
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/workspace/billing/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"enabled\": true}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.workspace.enable_billing(\n    enabled=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.workspace.enableBilling({\n  enabled: true,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.Workspace.EnableBilling(ctx, didit.TravelRuleWorkspaceBillingRequest{\n\tEnabled: didit.Bool(true),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleWorkspaceBillingRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().workspace().enableBilling(TravelRuleWorkspaceBillingRequest.builder()\n        .enabled(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->workspace->enableBilling([\n    'enabled' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.workspace.enable_billing(enabled: true)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Workspace.EnableBillingAsync(new TravelRuleWorkspaceBillingRequest\n{\n    Enabled = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'espace de travail avec `billing_enabled` à true.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWorkspace"
                }
              }
            }
          },
          "400": {
            "description": "`enabled` était false."
          },
          "404": {
            "description": "Cette application n'a pas rejoint avec l'offre gratuite, elle ne dispose donc d'aucun espace de travail gratuit."
          }
        }
      }
    },
    "/v3/investigator/summary/": {
      "get": {
        "operationId": "investigator_summary",
        "summary": "Résumé de l'enquêteur",
        "description": "Étape, décomptes des files d'attente, rapports préparés et décisions prises aujourd'hui, taux de concordance sur 30 jours, prix et niveau d'autonomie de chaque file d'attente. Les clés restreintes nécessitent la portée `decisions` (lecture) ; les alertes de transaction nécessitent également `transactions`.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "properties": {
                    "stage": {
                      "type": "string"
                    },
                    "last_report_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "prepared_today": {
                      "type": "integer"
                    },
                    "ready_to_accept": {
                      "type": "integer"
                    },
                    "open": {
                      "type": "integer"
                    },
                    "decided_today": {
                      "type": "integer"
                    },
                    "automation_rate_month": {
                      "type": "number",
                      "nullable": true
                    },
                    "preparing": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "query",
            "name": "scope",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "identity",
                "transactions"
              ],
              "default": "all"
            },
            "description": "`identity` (sessions, et dossiers non ouverts par une règle de transaction) ou `transactions` (alertes de transaction, et dossiers ouverts par une règle de transaction)."
          },
          {
            "in": "query",
            "name": "timezone",
            "schema": {
              "type": "string"
            },
            "description": "Fuseau horaire IANA (par exemple `Europe/Madrid`) qui sert à déterminer « aujourd'hui ». UTC par défaut."
          }
        ],
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "retrieve_summary",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.retrieve_summary()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.retrieveSummary();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.RetrieveSummary(ctx, didit.InvestigatorRetrieveSummaryParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().retrieveSummary();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->retrieveSummary();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.retrieve_summary\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.RetrieveSummaryAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/queue/": {
      "get": {
        "operationId": "investigator_queue",
        "summary": "Lister la file d'attente Investigator",
        "description": "Rapports ouverts, **Ready to accept** en premier, puis par date limite, risque et attente. `counts` couvre chaque type dans le périmètre. `count` est plafonné à 100. Les clés restreintes nécessitent la portée `decisions` (lecture) ; les alertes de transaction nécessitent également `transactions`.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "counts": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/InvestigatorQueueRow"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "query",
            "name": "scope",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "identity",
                "transactions"
              ],
              "default": "all"
            },
            "description": "`identity` (sessions, et dossiers non ouverts par une règle de transaction) ou `transactions` (alertes de transaction, et dossiers ouverts par une règle de transaction)."
          },
          {
            "in": "query",
            "name": "kind",
            "schema": {
              "type": "string"
            },
            "description": "`session`, `business_session`, `transaction` ou `case`, ou plusieurs de ces éléments séparés par des virgules."
          },
          {
            "in": "query",
            "name": "queue",
            "schema": {
              "type": "string",
              "enum": [
                "kyc",
                "kyb",
                "aml",
                "transactions",
                "cases"
              ]
            }
          },
          {
            "in": "query",
            "name": "recommendation",
            "schema": {
              "type": "string",
              "enum": [
                "approve",
                "decline",
                "escalate",
                "request"
              ]
            }
          },
          {
            "in": "query",
            "name": "confidence",
            "schema": {
              "type": "string",
              "enum": [
                "high",
                "moderate",
                "low"
              ]
            }
          },
          {
            "in": "query",
            "name": "ready",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "search",
            "schema": {
              "type": "string"
            },
            "description": "Nom, entreprise, titre du dossier, numéro, ID de transaction ou ID d'élément."
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "list_queue",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.investigator.list_queue():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.investigator.listQueue()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Investigator.ListQueueAutoPaging(ctx, didit.InvestigatorListQueueParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.investigator().listQueue()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->investigator->listQueue() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.investigator.list_queue.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Investigator.ListQueueAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/investigator/runs/{run_id}/": {
      "get": {
        "operationId": "investigator_run_retrieve",
        "summary": "Obtenir un rapport Investigator",
        "description": "Le rapport complet d'une exécution. 404 lorsque l'exécution n'a pas de rapport finalisé, ou que son élément a été supprimé. Les clés restreintes nécessitent la portée `decisions` (lecture) ; les alertes de transaction nécessitent également `transactions`.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvestigatorRunDetail"
                }
              }
            }
          },
          "404": {
            "description": "Introuvable, ou aucun rapport."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "run_id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "retrieve_run",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.retrieve_run(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.retrieveRun(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.RetrieveRun(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().retrieveRun(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->retrieveRun('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.retrieve_run(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.RetrieveRunAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/runs/{run_id}/accept/": {
      "post": {
        "operationId": "investigator_run_accept",
        "summary": "Accepter une recommandation",
        "description": "Applique l'action recommandée selon le chemin normal de l'élément, de sorte que vos webhooks habituels se déclenchent. Un `narrative` fait en sorte qu'elle soit modifiée et acceptée. Les clés restreintes nécessitent la portée `decisions` (écriture) ; les alertes de transaction nécessitent également `transactions` (écriture). Escalader une vérification ou une transaction ouvre un dossier.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvestigatorDecision"
                }
              }
            }
          },
          "409": {
            "description": "Déjà tranché, rapport non prêt, ou un garde-fou bloque l'élément."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "run_id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvestigatorAcceptRequest"
              },
              "example": {
                "send_email": false
              }
            }
          }
        },
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "accept_run",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.accept_run(\n    \"11111111-2222-3333-4444-555555555555\",\n    send_email=False,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.acceptRun(\"11111111-2222-3333-4444-555555555555\", {\n  send_email: false,\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.AcceptRun(ctx, \"11111111-2222-3333-4444-555555555555\", didit.InvestigatorAcceptRequest{\n\tSendEmail: didit.Bool(false),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.InvestigatorAcceptRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().acceptRun(\"11111111-2222-3333-4444-555555555555\", InvestigatorAcceptRequest.builder()\n        .sendEmail(false)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->acceptRun('11111111-2222-3333-4444-555555555555', [\n    'send_email' => false,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.accept_run(\n  \"11111111-2222-3333-4444-555555555555\",\n  send_email: false\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.AcceptRunAsync(\"11111111-2222-3333-4444-555555555555\", new InvestigatorAcceptRequest\n{\n    SendEmail = false,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/runs/{run_id}/override/": {
      "post": {
        "operationId": "investigator_run_override",
        "summary": "Remplacer une recommandation",
        "description": "Effectue une autre action avec une catégorie et un motif. Remplace également une décision prise de manière autonome par l'Investigator tant qu'elle est en vigueur. Les clés restreintes nécessitent le scope `decisions` (écriture) ; les alertes de transaction nécessitent également `transactions` (écriture). Faire remonter une vérification ou une transaction ouvre un dossier.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvestigatorDecision"
                }
              }
            }
          },
          "409": {
            "description": "Déjà tranché, ou un garde-fou bloque l'élément."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "run_id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvestigatorOverrideRequest"
              },
              "example": {
                "action": "decline",
                "category": "evidence_misread",
                "reason": "The proof of address is older than three months."
              }
            }
          }
        },
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "override_run",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.override_run(\n    \"11111111-2222-3333-4444-555555555555\",\n    action=\"decline\",\n    category=\"evidence_misread\",\n    reason=\"The proof of address is older than three months.\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.overrideRun(\"11111111-2222-3333-4444-555555555555\", {\n  action: \"decline\",\n  category: \"evidence_misread\",\n  reason: \"The proof of address is older than three months.\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.OverrideRun(ctx, \"11111111-2222-3333-4444-555555555555\", didit.InvestigatorOverrideRequest{\n\tAction:   \"decline\",\n\tCategory: \"evidence_misread\",\n\tReason:   \"The proof of address is older than three months.\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.InvestigatorOverrideRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().overrideRun(\"11111111-2222-3333-4444-555555555555\", InvestigatorOverrideRequest.builder()\n        .action(InvestigatorOverrideRequest.Action.of(\"decline\"))\n        .category(InvestigatorOverrideRequest.Category.of(\"evidence_misread\"))\n        .reason(\"The proof of address is older than three months.\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->overrideRun('11111111-2222-3333-4444-555555555555', [\n    'action' => 'decline',\n    'category' => 'evidence_misread',\n    'reason' => 'The proof of address is older than three months.',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.override_run(\n  \"11111111-2222-3333-4444-555555555555\",\n  action: \"decline\",\n  category: \"evidence_misread\",\n  reason: \"The proof of address is older than three months.\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.OverrideRunAsync(\"11111111-2222-3333-4444-555555555555\", new InvestigatorOverrideRequest\n{\n    Action = \"decline\",\n    Category = \"evidence_misread\",\n    Reason = \"The proof of address is older than three months.\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/runs/batch-accept/": {
      "post": {
        "operationId": "investigator_batch_accept",
        "summary": "Accepter les recommandations par lot",
        "description": "Accepte jusqu'à 50 rapports marqués comme prêts à être acceptés. Chacun constitue sa propre décision : un rapport ne pouvant être accepté est ignoré avec son motif. Les clés restreintes nécessitent la portée `decisions` (écriture) ; les alertes de transaction nécessitent également `transactions` (écriture). L'escalade d'une vérification ou d'une transaction ouvre un dossier.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvestigatorBatchAcceptResponse"
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvestigatorBatchAcceptRequest"
              }
            }
          }
        },
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "batch_accept_runs",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.batch_accept_runs(\n    run_ids=[\"11111111-2222-3333-4444-555555555555\"],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.batchAcceptRuns({\n  run_ids: [\"11111111-2222-3333-4444-555555555555\"],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.BatchAcceptRuns(ctx, didit.InvestigatorBatchAcceptRequest{\n\tRunIDs: []string{\"11111111-2222-3333-4444-555555555555\"},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.InvestigatorBatchAcceptRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().batchAcceptRuns(InvestigatorBatchAcceptRequest.builder()\n        .runIds(List.of(\"11111111-2222-3333-4444-555555555555\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->batchAcceptRuns([\n    'run_ids' => ['11111111-2222-3333-4444-555555555555'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.batch_accept_runs(run_ids: [\"11111111-2222-3333-4444-555555555555\"])\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.BatchAcceptRunsAsync(new InvestigatorBatchAcceptRequest\n{\n    RunIds = new string[] { \"11111111-2222-3333-4444-555555555555\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/transactions/{transaction_id}/": {
      "get": {
        "operationId": "investigator_transaction_retrieve",
        "summary": "Obtenir l'examen d'une transaction dans Investigator",
        "description": "Le dernier examen de la transaction, ou `investigator: null` lorsqu'elle n'en a jamais eu. Les clés restreintes nécessitent les portées `decisions` et `transactions` (lecture).",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transaction_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "investigator": {
                      "$ref": "#/components/schemas/InvestigatorBlock"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Transaction qui n'appartient pas à cette application."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "transaction_id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "retrieve_transaction",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.retrieve_transaction(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.retrieveTransaction(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.RetrieveTransaction(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().retrieveTransaction(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->retrieveTransaction('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.retrieve_transaction(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.RetrieveTransactionAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/guardrails/": {
      "get": {
        "operationId": "investigator_guardrails",
        "summary": "Lister les garde-fous verrouillés",
        "description": "Les cinq garde-fous qui s'appliquent à chaque file d'attente. Ils ne peuvent pas être désactivés. Les clés restreintes nécessitent la portée `decisions` (lecture) ; les alertes de transaction nécessitent également `transactions`.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string",
                            "enum": [
                              "sanctions_to_person",
                              "no_tipping_off",
                              "no_protected_characteristics",
                              "never_files_reports",
                              "every_decision_logged"
                            ]
                          },
                          "title": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "locked": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "list_guardrails",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.list_guardrails()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.listGuardrails();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.ListGuardrails(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().listGuardrails();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->listGuardrails();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.list_guardrails\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.ListGuardrailsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/dashboard/": {
      "get": {
        "operationId": "investigator_dashboard",
        "summary": "Tableau de bord de l'enquêteur",
        "description": "Les 30 derniers jours : examens, décisions, taux d'automatisation, heures économisées, dépenses, dérogations, échantillons de qualité depuis le lancement, chiffres par file d'attente et hebdomadaires. Les clés restreintes nécessitent la portée `decisions` (lecture) ; les alertes de transaction nécessitent également `transactions`.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "properties": {
                    "stage": {
                      "type": "string"
                    },
                    "window_days": {
                      "type": "integer"
                    },
                    "reviews": {
                      "type": "integer"
                    },
                    "decided": {
                      "type": "integer"
                    },
                    "automated": {
                      "type": "integer"
                    },
                    "automation_rate": {
                      "type": "number",
                      "nullable": true
                    },
                    "hours_saved": {
                      "type": "number",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "query",
            "name": "scope",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "identity",
                "transactions"
              ],
              "default": "all"
            },
            "description": "`identity` (sessions, et dossiers non ouverts par une règle de transaction) ou `transactions` (alertes de transaction, et dossiers ouverts par une règle de transaction)."
          }
        ],
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "retrieve_dashboard",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.retrieve_dashboard()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.retrieveDashboard();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.RetrieveDashboard(ctx, didit.InvestigatorRetrieveDashboardParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().retrieveDashboard();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->retrieveDashboard();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.retrieve_dashboard\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.RetrieveDashboardAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/performance/": {
      "get": {
        "operationId": "investigator_performance",
        "summary": "Performance de l'enquêteur",
        "description": "Concordance avec votre équipe, volume, temps gagné, calibrage de la confiance, résultats par file d'attente, motifs de dérogation et désaccords pour une période. Les clés restreintes nécessitent le périmètre `decisions` (lecture) ; les alertes de transaction nécessitent également `transactions`.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "properties": {
                    "period": {
                      "type": "integer"
                    },
                    "start": {
                      "type": "string",
                      "format": "date"
                    },
                    "end": {
                      "type": "string",
                      "format": "date"
                    },
                    "investigated": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "query",
            "name": "scope",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "identity",
                "transactions"
              ],
              "default": "all"
            },
            "description": "`identity` (sessions, et dossiers non ouverts par une règle de transaction) ou `transactions` (alertes de transaction, et dossiers ouverts par une règle de transaction)."
          },
          {
            "in": "query",
            "name": "period",
            "schema": {
              "type": "string",
              "enum": [
                "7",
                "30",
                "90"
              ],
              "default": "30"
            },
            "description": "Nombre de jours, se terminant aujourd'hui."
          }
        ],
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "retrieve_performance",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.retrieve_performance()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.retrievePerformance();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.RetrievePerformance(ctx, didit.InvestigatorRetrievePerformanceParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().retrievePerformance();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->retrievePerformance();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.retrieve_performance\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.RetrievePerformanceAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/investigator/activity/": {
      "get": {
        "operationId": "investigator_activity",
        "summary": "Lister l'activité d'Investigator",
        "description": "Le journal d'audit en ajout uniquement, le plus récent en premier. Une acceptation par lot correspond à une seule entrée. Ajoute `counts` par groupe et `actors`. Les clés restreintes nécessitent la portée `decisions` (lecture) ; les alertes de transaction nécessitent également `transactions`.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "counts": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "actors": {
                      "type": "array",
                      "items": {}
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "`id`, `at`, `kind`, `group`, `queue`, `run_id`, `item`, `actor`, `agent_version`, `data`, `report_version`, `steps`, `sources`, `batch`."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "query",
            "name": "scope",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "identity",
                "transactions"
              ],
              "default": "all"
            },
            "description": "`identity` (sessions, et dossiers non ouverts par une règle de transaction) ou `transactions` (alertes de transaction, et dossiers ouverts par une règle de transaction)."
          },
          {
            "in": "query",
            "name": "group",
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "decisions",
                "overrides",
                "autonomy"
              ]
            }
          },
          {
            "in": "query",
            "name": "actor",
            "schema": {
              "type": "string"
            },
            "description": "`agent` pour l'Investigator, ou l'e-mail d'une personne."
          },
          {
            "in": "query",
            "name": "since",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "until",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "list_activity",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.investigator.list_activity():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.investigator.listActivity()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.Investigator.ListActivityAutoPaging(ctx, didit.InvestigatorListActivityParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.investigator().listActivity()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->investigator->listActivity() as $item) {\n    print_r($item);\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.investigator.list_activity.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.Investigator.ListActivityAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/investigator/activity/export/": {
      "get": {
        "operationId": "investigator_activity_export",
        "summary": "Exporter l'activité d'Investigator",
        "description": "Les mêmes entrées au format CSV, une ligne par décision, de la plus récente à la plus ancienne, jusqu'à 10,000 entrées. Les clés restreintes nécessitent le scope `decisions` (read) ; les alertes de transaction nécessitent également `transactions`.",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "parameters": [
          {
            "in": "query",
            "name": "scope",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "identity",
                "transactions"
              ],
              "default": "all"
            },
            "description": "`identity` (sessions, et dossiers non ouverts par une règle de transaction) ou `transactions` (alertes de transaction, et dossiers ouverts par une règle de transaction)."
          },
          {
            "in": "query",
            "name": "group",
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "decisions",
                "overrides",
                "autonomy"
              ]
            }
          },
          {
            "in": "query",
            "name": "actor",
            "schema": {
              "type": "string"
            },
            "description": "`agent` pour l'Investigator, ou l'e-mail d'une personne."
          },
          {
            "in": "query",
            "name": "since",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "until",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "export_activity",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\ncontent = client.investigator.export_activity()\nwith open(\"download.csv\", \"wb\") as file:\n    file.write(content)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import { writeFile } from \"node:fs/promises\";\nimport Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst content = await didit.investigator.exportActivity();\nawait writeFile(\"download.csv\", Buffer.from(await content.arrayBuffer()));"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresp, err := client.Investigator.ExportActivity(ctx, didit.InvestigatorExportActivityParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer resp.Body.Close()\nfile, err := os.Create(\"download.csv\")\nif err != nil {\n\tlog.Fatal(err)\n}\ndefer file.Close()\nif _, err := io.Copy(file, resp.Body); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.investigator().exportActivity()\n        .writeTo(Path.of(\"download.csv\"));"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$content = $didit->investigator->exportActivity();\n$content->saveTo('download.csv');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ncontent = didit.investigator.export_activity\nFile.binwrite(\"download.csv\", content)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar content = await client.Investigator.ExportActivityAsync();\nawait content.SaveToAsync(\"download.csv\");"
          }
        ]
      }
    },
    "/v3/investigator/settings/": {
      "get": {
        "operationId": "investigator_settings_retrieve",
        "summary": "Obtenir les paramètres d'Investigator",
        "description": "La phase (`none`, `shadow` ou `live`) et la limite de dépense mensuelle accompagnée des dépenses de ce mois. Les clés restreintes nécessitent la portée `applications` (lecture).",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvestigatorSettings"
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "retrieve_settings",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.retrieve_settings()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.retrieveSettings();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.RetrieveSettings(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().retrieveSettings();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->retrieveSettings();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.retrieve_settings\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.RetrieveSettingsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "patch": {
        "operationId": "investigator_settings_update",
        "summary": "Mettre à jour les paramètres de l'investigateur",
        "description": "Modifier l'étape, la limite de dépenses mensuelle ou les deux. Passer au-delà de `none` nécessite un forfait incluant l'Investigator (Growth ou supérieur) ; `live` nécessite également un contrat fixant son prix, si vous en avez un. Les clés restreintes nécessitent le scope `applications` (écriture).",
        "tags": [
          "Investigator"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvestigatorSettings"
                }
              }
            }
          },
          "400": {
            "description": "Aucun champ envoyé, ou valeur invalide."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "La clé ne dispose pas de la portée requise, le type d'élément n'est pas lisible ou le forfait n'inclut pas Investigator."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvestigatorSettings"
              },
              "example": {
                "stage": "shadow",
                "monthly_spend_limit": "500.00"
              }
            }
          }
        },
        "x-didit-sdk": {
          "resource": "investigator",
          "method": "update_settings",
          "auth": "api_key",
          "server": true
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.investigator.update_settings(\n    stage=\"shadow\",\n    monthly_spend_limit=\"500.00\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.investigator.updateSettings({\n  stage: \"shadow\",\n  monthly_spend_limit: \"500.00\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Investigator.UpdateSettings(ctx, didit.InvestigatorSettingsParam{\n\tStage:             didit.Some(didit.InvestigatorSettingsStage(\"shadow\")),\n\tMonthlySpendLimit: didit.String(\"500.00\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.InvestigatorSettings;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.investigator().updateSettings(InvestigatorSettings.builder()\n        .stage(InvestigatorSettings.Stage.of(\"shadow\"))\n        .monthlySpendLimit(\"500.00\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->investigator->updateSettings([\n    'stage' => 'shadow',\n    'monthly_spend_limit' => '500.00',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.investigator.update_settings(\n  stage: \"shadow\",\n  monthly_spend_limit: \"500.00\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Investigator.UpdateSettingsAsync(new InvestigatorSettings\n{\n    Stage = new InvestigatorSettingsStage(\"shadow\"),\n    MonthlySpendLimit = \"500.00\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/travel-rule/wallet-addresses/import/": {
      "post": {
        "summary": "Importer des adresses de portefeuille en masse",
        "description": "Ajoutez jusqu'à 10 000 portefeuilles à votre carnet d'adresses Travel Rule en un seul appel, sous forme de JSON ou de fichier CSV. Un portefeuille peut être envoyé par son adresse, par le SHA-256 de son adresse en minuscules (`address_hash`) pour préserver la confidentialité de l'adresse, ou les deux. L'importation est idempotente : un portefeuille déjà présent dans le carnet est signalé comme `existing` et n'est pas modifié, ce qui permet de renvoyer le même fichier. Chaque ligne est validée individuellement, de sorte qu'une ligne erronée ne fait jamais échouer les autres. Un portefeuille importé par son hash correspond uniquement aux transferts vers cette adresse et sa possession peut être prouvée à l'aide du widget de vérification de possession de portefeuille comme toute autre entrée.",
        "operationId": "importTravelRuleWalletAddresses",
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-didit-sdk": {
          "resource": "travel_rule.wallet_addresses",
          "method": "bulk_import",
          "auth": "api_key",
          "server": true
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": [
                      "entries"
                    ],
                    "properties": {
                      "entries": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 10000,
                        "items": {
                          "$ref": "#/components/schemas/WalletAddressImportRow"
                        }
                      }
                    }
                  },
                  {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 10000,
                    "items": {
                      "$ref": "#/components/schemas/WalletAddressImportRow"
                    }
                  }
                ]
              },
              "example": {
                "entries": [
                  {
                    "address": "0xBeneficiaryWallet01",
                    "chain": "ETH",
                    "holder_name": "Ana Diaz",
                    "holder_vendor_data": "user-042"
                  },
                  {
                    "address_hash": "4f7d2e1c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e",
                    "chain": "bitcoin",
                    "holder_vendor_data": "user-043"
                  },
                  {
                    "address": "rExchangeSharedAddress01",
                    "chain": "XRP",
                    "memo": "104729",
                    "holder_name": "Ana Diaz"
                  }
                ]
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Un fichier CSV en UTF-8 d'au maximum 5 MB avec une ligne d'en-tête nommant ses colonnes (les champs de ligne ou leurs alias). Les cellules vides sont considérées comme non envoyées ; les colonnes que l'importation ne lit pas sont ignorées."
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl (JSON)",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/wallet-addresses/import/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"entries\": [{\"address\": \"0xBeneficiaryWallet01\", \"chain\": \"ETH\", \"holder_name\": \"Ana Diaz\"}, {\"address\": \"rExchangeSharedAddress01\", \"chain\": \"XRP\", \"memo\": \"104729\"}]}'"
          },
          {
            "lang": "curl",
            "label": "curl (CSV)",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/wallet-addresses/import/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -F 'file=@wallets.csv;type=text/csv'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.wallet_addresses.bulk_import(\n    body={\n        \"entries\": [{\n            \"address\": \"0xBeneficiaryWallet01\",\n            \"chain\": \"ETH\",\n            \"holder_name\": \"Ana Diaz\",\n            \"holder_vendor_data\": \"user-042\",\n        }, {\n            \"address_hash\": \"4f7d2e1c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e\",\n            \"chain\": \"bitcoin\",\n            \"holder_vendor_data\": \"user-043\",\n        }, {\n            \"address\": \"rExchangeSharedAddress01\",\n            \"chain\": \"XRP\",\n            \"memo\": \"104729\",\n            \"holder_name\": \"Ana Diaz\",\n        }],\n    },\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.walletAddresses.bulkImport({\n  file: await fileFromPath(\"wallet-addresses.csv\"),\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.WalletAddresses.BulkImport(ctx, didit.TravelRuleWalletAddressesBulkImportParams{\n\tFile: didit.Some(didit.FileFromPath(\"wallet-addresses.csv\")),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport me.didit.Didit;\nimport me.didit.types.TravelRuleWalletAddressesBulkImportParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().walletAddresses().bulkImport(TravelRuleWalletAddressesBulkImportParams.builder()\n        .file(Path.of(\"wallet-addresses.csv\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->walletAddresses->bulkImport([\n    'file' => File::fromPath('wallet-addresses.csv'),\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.wallet_addresses.bulk_import(\n  body: {\n    entries: [{\n      address: \"0xBeneficiaryWallet01\",\n      chain: \"ETH\",\n      holder_name: \"Ana Diaz\",\n      holder_vendor_data: \"user-042\",\n    }, {\n      address_hash: \"4f7d2e1c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e\",\n      chain: \"bitcoin\",\n      holder_vendor_data: \"user-043\",\n    }, {\n      address: \"rExchangeSharedAddress01\",\n      chain: \"XRP\",\n      memo: \"104729\",\n      holder_name: \"Ana Diaz\",\n    }],\n  }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.WalletAddresses.BulkImportAsync(new TravelRuleWalletAddressesBulkImportParams\n{\n    File = FileUpload.FromPath(\"wallet-addresses.csv\"),\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Chaque ligne a été créée, existait déjà dans le registre ou était une répétition d'une ligne précédente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletAddressImportReport"
                },
                "example": {
                  "total": 3,
                  "created": 2,
                  "existing": 1,
                  "duplicate": 0,
                  "failed": 0,
                  "rows": [
                    {
                      "row": 1,
                      "status": "existing",
                      "entry_id": "11111111-2222-3333-4444-555555555555",
                      "errors": {},
                      "duplicate_of_row": null
                    },
                    {
                      "row": 2,
                      "status": "created",
                      "entry_id": "22222222-3333-4444-5555-666666666666",
                      "errors": {},
                      "duplicate_of_row": null
                    },
                    {
                      "row": 3,
                      "status": "created",
                      "entry_id": "33333333-4444-5555-6666-777777777777",
                      "errors": {},
                      "duplicate_of_row": null
                    }
                  ]
                }
              }
            }
          },
          "207": {
            "description": "Au moins une ligne a échoué ; les autres ont été importées. Chaque ligne ayant échoué indique ses erreurs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletAddressImportReport"
                },
                "example": {
                  "total": 2,
                  "created": 1,
                  "existing": 0,
                  "duplicate": 0,
                  "failed": 1,
                  "rows": [
                    {
                      "row": 1,
                      "status": "created",
                      "entry_id": "44444444-5555-6666-7777-888888888888",
                      "errors": {},
                      "duplicate_of_row": null
                    },
                    {
                      "row": 2,
                      "status": "failed",
                      "entry_id": null,
                      "errors": {
                        "address": [
                          "Send address, address_hash or both."
                        ]
                      },
                      "duplicate_of_row": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "La requête elle-même ne peut pas être lue : présence simultanée de `entries` et d'un `file`, ou aucun des deux ; plus de 10 000 lignes ; un fichier de plus de 5 Mo, non CSV UTF-8, sans ligne d'en-tête ou sans lignes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "file": [
                    "At most 10000 rows per import."
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/counterparty-contacts/": {
      "get": {
        "summary": "Lister les contacts de la contrepartie",
        "description": "Les adresses de conformité auxquelles le canal EMAIL peut écrire pour votre application : les contacts de la plateforme Didit ainsi que les contacts privés de votre application, y compris celles ayant généré un rebond, du plus récent au plus ancien. Paginé avec `limit` (50 par défaut) et `offset` ; `count` s'arrête à 100, donc 100 signifie 100 ou plus.",
        "operationId": "listTravelRuleCounterpartyContacts",
        "x-didit-sdk": {
          "resource": "travel_rule.counterparty_contacts",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "counterparty",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Uniquement les contacts de cette entrée de l'annuaire. Doit être un UUID ; une valeur vide signifie aucun filtre."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Taille de page, 50 par défaut."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Lignes à ignorer."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/travel-rule/counterparty-contacts/?counterparty={vasp_id}' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.travel_rule.counterparty_contacts.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.travelRule.counterpartyContacts.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.TravelRule.CounterpartyContacts.ListAutoPaging(ctx, didit.TravelRuleCounterpartyContactsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.travelRule().counterpartyContacts().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->travelRule->counterpartyContacts->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.travel_rule.counterparty_contacts.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.TravelRule.CounterpartyContacts.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Les contacts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TravelRuleCounterpartyContact"
                      }
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next": null,
                  "previous": null,
                  "results": [
                    {
                      "uuid": "6c1f9b8e-2d4a-4f7e-8b3c-5a9d0e1f2a3b",
                      "counterparty": "0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91",
                      "counterparty_name": "Example Counterparty VASP",
                      "email": "compliance@counterparty.example",
                      "name": "Compliance desk",
                      "source": "application",
                      "scope": "application",
                      "created_by": "",
                      "verified_at": null,
                      "is_invalid": false,
                      "invalid_reason": "",
                      "invalid_detail": "",
                      "invalid_at": null,
                      "created_at": "2026-10-19T09:00:00Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`counterparty` n'est pas un UUID.",
            "content": {
              "application/json": {
                "example": {
                  "counterparty": [
                    "Must be a valid UUID."
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Ajouter un contact de contrepartie",
        "description": "Ajoute une adresse de conformité privée pour une entrée de l'annuaire. Seule votre application la voit et l'utilise, et le rail EMAIL écrit vers celle-ci avant tout contact de la plateforme. Ajouter une adresse que l'entrée possède déjà parmi vos propres contacts renvoie ce contact.",
        "operationId": "createTravelRuleCounterpartyContact",
        "x-didit-sdk": {
          "resource": "travel_rule.counterparty_contacts",
          "method": "create",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleCounterpartyContactCreate"
              },
              "example": {
                "counterparty": "0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91",
                "email": "compliance@counterparty.example",
                "name": "Compliance desk"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/counterparty-contacts/ \\\n  -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \\\n  -d '{\"counterparty\": \"0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91\", \"email\": \"compliance@counterparty.example\", \"name\": \"Compliance desk\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.counterparty_contacts.create(\n    counterparty=\"0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91\",\n    email=\"compliance@counterparty.example\",\n    name=\"Compliance desk\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.counterpartyContacts.create({\n  counterparty: \"0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91\",\n  email: \"compliance@counterparty.example\",\n  name: \"Compliance desk\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.CounterpartyContacts.Create(ctx, didit.TravelRuleCounterpartyContactCreate{\n\tCounterparty: \"0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91\",\n\tEmail:        \"compliance@counterparty.example\",\n\tName:         didit.String(\"Compliance desk\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleCounterpartyContactCreate;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().counterpartyContacts().create(TravelRuleCounterpartyContactCreate.builder()\n        .counterparty(\"0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91\")\n        .email(\"compliance@counterparty.example\")\n        .name(\"Compliance desk\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->counterpartyContacts->create([\n    'counterparty' => '0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91',\n    'email' => 'compliance@counterparty.example',\n    'name' => 'Compliance desk',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.counterparty_contacts.create(\n  counterparty: \"0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91\",\n  email: \"compliance@counterparty.example\",\n  name: \"Compliance desk\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.CounterpartyContacts.CreateAsync(new TravelRuleCounterpartyContactCreate\n{\n    Counterparty = \"0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91\",\n    Email = \"compliance@counterparty.example\",\n    Name = \"Compliance desk\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "201": {
            "description": "Le contact a été ajouté.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleCounterpartyContact"
                },
                "example": {
                  "uuid": "6c1f9b8e-2d4a-4f7e-8b3c-5a9d0e1f2a3b",
                  "counterparty": "0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91",
                  "counterparty_name": "Example Counterparty VASP",
                  "email": "compliance@counterparty.example",
                  "name": "Compliance desk",
                  "source": "application",
                  "scope": "application",
                  "created_by": "",
                  "verified_at": null,
                  "is_invalid": false,
                  "invalid_reason": "",
                  "invalid_detail": "",
                  "invalid_at": null,
                  "created_at": "2026-10-19T09:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Un champ est manquant ou non valide, ou aucune entrée de l'annuaire ne possède cet identifiant.",
            "content": {
              "application/json": {
                "example": {
                  "counterparty": [
                    "No directory entry with this id."
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/counterparty-contacts/{contact_uuid}/": {
      "delete": {
        "summary": "Supprimer un contact de contrepartie",
        "description": "Supprime l'un des contacts propres à votre application. Le canal EMAIL cesse immédiatement d'écrire vers ce contact. Les contacts de la plateforme ne peuvent pas être supprimés.",
        "operationId": "deleteTravelRuleCounterpartyContact",
        "x-didit-sdk": {
          "resource": "travel_rule.counterparty_contacts",
          "method": "delete",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "contact_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X DELETE https://verification.didit.me/v3/travel-rule/counterparty-contacts/{contact_uuid}/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.travel_rule.counterparty_contacts.delete(\n    \"11111111-2222-3333-4444-555555555555\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.travelRule.counterpartyContacts.delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.TravelRule.CounterpartyContacts.Delete(ctx, \"11111111-2222-3333-4444-555555555555\"); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.travelRule().counterpartyContacts().delete(\"11111111-2222-3333-4444-555555555555\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->travelRule->counterpartyContacts->delete('11111111-2222-3333-4444-555555555555');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.travel_rule.counterparty_contacts.delete(\"11111111-2222-3333-4444-555555555555\")"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.TravelRule.CounterpartyContacts.DeleteAsync(\"11111111-2222-3333-4444-555555555555\");"
          }
        ],
        "responses": {
          "204": {
            "description": "Supprimé."
          },
          "404": {
            "description": "Aucun contact de votre application ne possède cet identifiant. Un contact de plateforme renvoie également 404."
          }
        }
      }
    },
    "/v3/travel-rule/transfers/": {
      "get": {
        "summary": "Lister les transferts Travel Rule",
        "description": "Les transferts Travel Rule de votre application, du plus récent au plus ancien, paginés avec `limit` (50 par défaut) et `offset`. Les lignes contiennent uniquement les noms de VASP, les portefeuilles et les mémos, jamais de données personnelles. Des valeurs séparées par des virgules permettent d'en sélectionner plusieurs. Une valeur inconnue renvoie 400 en nommant le paramètre, par exemple `{\"direction\": [\"Unknown value(s): inbound.\"]}`.",
        "operationId": "listTravelRuleTransfers",
        "x-didit-sdk": {
          "resource": "travel_rule.transfers",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "INBOUND, OUTBOUND, ou les deux séparés par une virgule. Sensible à la casse."
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Un ou plusieurs statuts de transfert, séparés par des virgules."
          },
          {
            "name": "rail",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Un ou plusieurs parmi INTERNAL, TRP, GTR, TRUST, VERIFYVASP, SYGNA, EMAIL, TEST_VASP, séparés par des virgules."
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "withdrawal, deposit ou message, séparés par des virgules."
          },
          {
            "name": "currency",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "La devise de la transaction, insensible à la casse."
          },
          {
            "name": "start_date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Transferts créés à cette date ou après (UTC), YYYY-MM-DD."
          },
          {
            "name": "end_date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Transferts créés à cette date ou avant (UTC), YYYY-MM-DD."
          },
          {
            "name": "counterparty",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'`id` d'une entrée d'annuaire ou d'un membre du réseau Didit provenant de GET /v3/travel-rule/vasps/ : vos transferts avec cette contrepartie. Une valeur qui n'est pas un identifiant valide renvoie une réponse 400."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Taille de page, 50 par défaut."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Lignes à ignorer."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/travel-rule/transfers/?direction=OUTBOUND&status=AWAITING_COUNTERPARTY' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.travel_rule.transfers.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.travelRule.transfers.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.TravelRule.Transfers.ListAutoPaging(ctx, didit.TravelRuleTransfersListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.travelRule().transfers().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->travelRule->transfers->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.travel_rule.transfers.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.TravelRule.Transfers.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de transferts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TravelRuleTransferRow"
                      }
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next": null,
                  "previous": null,
                  "results": [
                    {
                      "id": "5b0f6c2e-2a4d-4f0e-9a41-0c3f9a7e1d22",
                      "transaction_id": "a3c1e8f4-7b62-4d1a-8e0b-2f9d6c4b7a10",
                      "txn_id": "wd-2026-10-19-0042",
                      "txn_date": "2026-10-19T08:41:12Z",
                      "kind": "withdrawal",
                      "direction": "OUTBOUND",
                      "status": "AWAITING_COUNTERPARTY",
                      "rail": "TRP",
                      "asset": "ETH",
                      "amount": "1.25",
                      "originator_vasp": "Origin CASP SL",
                      "beneficiary_vasp": "Example Counterparty VASP",
                      "originator_wallet": "0x77ccff0cc624a53cd8b8d8703ced826710211ec7",
                      "beneficiary_wallet": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
                      "originator_memo": "",
                      "beneficiary_memo": "",
                      "originator_wallet_type": "vasp",
                      "beneficiary_wallet_type": "vasp",
                      "matched_transaction_id": null,
                      "deadline_at": "2026-10-21T08:41:13Z",
                      "created_at": "2026-10-19T08:41:13Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Une valeur de filtre n'est pas valide.",
            "content": {
              "application/json": {
                "example": {
                  "start_date": [
                    "Use the YYYY-MM-DD format."
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v3/session/imports/providers/": {
      "get": {
        "summary": "Lister les fournisseurs de migration",
        "description": "Les 15 fournisseurs depuis lesquels vous pouvez migrer des vérifications : ce dont chacun a besoin pour se connecter, si son API peut lister les enregistrements, les autorisations nécessaires pour sa clé et sa correspondance de statuts par défaut.",
        "operationId": "get_v3_session_imports_providers_list",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "list_providers",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "responses": {
          "200": {
            "description": "Fournisseurs de migration.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "providers": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ImportProvider"
                      }
                    },
                    "mapping_targets": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "skipped_statuses": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.list_providers()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.listProviders();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.ListProviders(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().listProviders();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->listProviders();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.list_providers\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.ListProvidersAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/imports/providers/check/": {
      "post": {
        "summary": "Vérifier une clé de fournisseur",
        "description": "Consultez le fournisseur avec votre clé avant de créer une migration. Rien n'est stocké.",
        "operationId": "post_v3_session_imports_providers_check",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "check_provider",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "sumsub",
                      "jumio",
                      "veriff",
                      "onfido",
                      "persona",
                      "metamap",
                      "socure",
                      "idnow",
                      "shufti",
                      "idenfy",
                      "ondato",
                      "trulioo",
                      "au10tix",
                      "complycube",
                      "other"
                    ],
                    "description": "Source de migration, obtenue via `GET /v3/session/imports/providers/`. Requis lorsque `source` vaut `provider`."
                  },
                  "credentials": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "La clé en lecture seule du fournisseur, contenant les noms de champs listés par `credential_fields`. Chiffrée au repos, jamais renvoyée et effacée à la fin de l'importation. Envoyez-la sous forme de chaîne JSON dans du multipart."
                  },
                  "options": {
                    "type": "object",
                    "properties": {
                      "region": {
                        "type": "string",
                        "description": "La région du fournisseur, l'une de ses `regions` (Onfido : `eu`, `us`, `ca`)."
                      }
                    }
                  },
                  "record_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Pour les fournisseurs `api_ids` : le premier identifiant d'enregistrement de votre export."
                  }
                },
                "required": [
                  "provider",
                  "credentials"
                ]
              },
              "example": {
                "provider": "sumsub",
                "credentials": {
                  "app_token": "YOUR_PROVIDER_APP_TOKEN",
                  "secret_key": "YOUR_PROVIDER_SECRET_KEY"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "La clé peut lire les enregistrements.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "credential_hint": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le fournisseur a refusé la clé : `code`, `detail`, `missing_permissions`, `suggested_region`."
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.check_provider(\n    provider=\"sumsub\",\n    credentials={\"app_token\": \"YOUR_PROVIDER_APP_TOKEN\", \"secret_key\": \"YOUR_PROVIDER_SECRET_KEY\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.checkProvider({\n  provider: \"sumsub\",\n  credentials: { app_token: \"YOUR_PROVIDER_APP_TOKEN\", secret_key: \"YOUR_PROVIDER_SECRET_KEY\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.CheckProvider(ctx, didit.SessionsImportsCheckProviderParams{\n\tProvider:    \"sumsub\",\n\tCredentials: map[string]string{\"app_token\": \"YOUR_PROVIDER_APP_TOKEN\", \"secret_key\": \"YOUR_PROVIDER_SECRET_KEY\"},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.SessionsImportsCheckProviderParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().checkProvider(SessionsImportsCheckProviderParams.builder()\n        .provider(SessionsImportsCheckProviderParams.Provider.of(\"sumsub\"))\n        .credentials(Map.of(\"app_token\", \"YOUR_PROVIDER_APP_TOKEN\", \"secret_key\", \"YOUR_PROVIDER_SECRET_KEY\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->checkProvider([\n    'provider' => 'sumsub',\n    'credentials' => ['app_token' => 'YOUR_PROVIDER_APP_TOKEN', 'secret_key' => 'YOUR_PROVIDER_SECRET_KEY'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.check_provider(\n  provider: \"sumsub\",\n  credentials: { app_token: \"YOUR_PROVIDER_APP_TOKEN\", secret_key: \"YOUR_PROVIDER_SECRET_KEY\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.CheckProviderAsync(new SessionsImportsCheckProviderParams\n{\n    Provider = \"sumsub\",\n    Credentials = new Dictionary<string, string> { [\"app_token\"] = \"YOUR_PROVIDER_APP_TOKEN\", [\"secret_key\"] = \"YOUR_PROVIDER_SECRET_KEY\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/imports/{importId}/start/": {
      "post": {
        "summary": "Démarrer une exécution à blanc",
        "description": "Démarrer une migration dont l'exécution à blanc (dry run) s'est terminée (`READY`) : la même tâche importe pour de vrai, avec le mappage de statut et le choix des gabarits biométriques tels qu'envoyés maintenant.",
        "operationId": "post_v3_session_imports_start",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "start",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status_mapping": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string",
                      "enum": [
                        "Approved",
                        "Declined",
                        "In Review",
                        "Expired",
                        "Not Finished",
                        "Abandoned"
                      ]
                    },
                    "description": "Modifications du mappage de statuts par défaut du fournisseur : statut source vers statut Didit. `Not Finished` et `Abandoned` sont ignorés et comptabilisés, jamais importés."
                  },
                  "face_templates": {
                    "type": "boolean",
                    "default": false,
                    "description": "Générez des gabarits biométriques à partir des selfies importés et recherchez-les parmi les visages et la liste de blocage de l'application. Les correspondances sont signalées uniquement pour examen. Nécessite `lawful_basis_confirmed`."
                  },
                  "lawful_basis_confirmed": {
                    "type": "boolean",
                    "default": false,
                    "description": "Confirme que vous disposez d'une base légale pour partager ces selfies avec Didit en tant que sous-traitant."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "La tâche d'importation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionImportJob"
                }
              }
            }
          },
          "400": {
            "description": "La tâche n'est pas dans un état auquel cette action s'applique."
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.start(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.start(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.Start(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsImportsStartParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().start(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->start('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.start(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.StartAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/imports/{importId}/pause/": {
      "post": {
        "summary": "Mettre en pause une tâche d'importation",
        "description": "Suspendre une importation en file d'attente ou en cours d'exécution.",
        "operationId": "post_v3_session_imports_pause",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "pause",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La tâche d'importation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionImportJob"
                }
              }
            }
          },
          "400": {
            "description": "La tâche n'est pas dans un état auquel cette action s'applique."
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.pause(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.pause(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.Pause(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().pause(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->pause('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.pause(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.PauseAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/imports/{importId}/resume/": {
      "post": {
        "summary": "Reprendre une tâche d'importation",
        "description": "Reprendre une importation que vous avez mise en pause. Une tâche mise en pause en raison de la limite de débit du fournisseur reprend d'elle-même.",
        "operationId": "post_v3_session_imports_resume",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "resume",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La tâche d'importation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionImportJob"
                }
              }
            }
          },
          "400": {
            "description": "La tâche n'est pas dans un état auquel cette action s'applique."
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.resume(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.resume(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.Resume(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().resume(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->resume('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.resume(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.ResumeAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/imports/{importId}/cancel/": {
      "post": {
        "summary": "Annuler une tâche d'importation",
        "description": "Annuler une importation. Les éléments déjà importés sont conservés ; le fichier téléversé et la clé sont effacés.",
        "operationId": "post_v3_session_imports_cancel",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "cancel",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La tâche d'importation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionImportJob"
                }
              }
            }
          },
          "400": {
            "description": "La tâche n'est pas dans un état auquel cette action s'applique."
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.cancel(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.cancel(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.Cancel(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().cancel(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->cancel('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.cancel(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.CancelAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/imports/{importId}/retry/": {
      "post": {
        "summary": "Réessayer une migration",
        "description": "Exécuter à nouveau une migration terminée sous la forme d'un nouveau travail, avec une nouvelle clé (l'ancienne ayant été effacée). Cela conserve le fournisseur, le workflow, la région, le mappage des statuts et le choix des gabarits biométriques ; tout ce qui se trouve déjà dans Didit est ignoré.",
        "operationId": "post_v3_session_imports_retry",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "retry",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "credentials": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "La clé en lecture seule du fournisseur, contenant les noms de champs listés par `credential_fields`. Chiffrée au repos, jamais renvoyée et effacée à la fin de l'importation. Envoyez-la sous forme de chaîne JSON dans du multipart."
                  },
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Les identifiants d'enregistrement ou le fichier d'export à nouveau, pour les fournisseurs `api_ids` et `export_file`."
                  }
                }
              },
              "example": {
                "credentials": {
                  "app_token": "YOUR_PROVIDER_APP_TOKEN",
                  "secret_key": "YOUR_PROVIDER_SECRET_KEY"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "La nouvelle tâche d'importation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionImportJob"
                }
              }
            }
          },
          "400": {
            "description": "Pas une migration, pas terminée, ou le fournisseur a refusé la clé."
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.retry(\n    \"11111111-2222-3333-4444-555555555555\",\n    credentials={\"app_token\": \"YOUR_PROVIDER_APP_TOKEN\", \"secret_key\": \"YOUR_PROVIDER_SECRET_KEY\"},\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.retry(\"11111111-2222-3333-4444-555555555555\", {\n  credentials: { app_token: \"YOUR_PROVIDER_APP_TOKEN\", secret_key: \"YOUR_PROVIDER_SECRET_KEY\" },\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.Retry(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsImportsRetryParams{\n\tCredentials: didit.Some(map[string]string{\"app_token\": \"YOUR_PROVIDER_APP_TOKEN\", \"secret_key\": \"YOUR_PROVIDER_SECRET_KEY\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.Map;\nimport me.didit.Didit;\nimport me.didit.types.SessionsImportsRetryParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().retry(\"11111111-2222-3333-4444-555555555555\", SessionsImportsRetryParams.builder()\n        .credentials(Map.of(\"app_token\", \"YOUR_PROVIDER_APP_TOKEN\", \"secret_key\", \"YOUR_PROVIDER_SECRET_KEY\"))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->retry('11111111-2222-3333-4444-555555555555', [\n    'credentials' => ['app_token' => 'YOUR_PROVIDER_APP_TOKEN', 'secret_key' => 'YOUR_PROVIDER_SECRET_KEY'],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.retry(\n  \"11111111-2222-3333-4444-555555555555\",\n  credentials: { app_token: \"YOUR_PROVIDER_APP_TOKEN\", secret_key: \"YOUR_PROVIDER_SECRET_KEY\" }\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.RetryAsync(\"11111111-2222-3333-4444-555555555555\", new SessionsImportsRetryParams\n{\n    Credentials = new Dictionary<string, string> { [\"app_token\"] = \"YOUR_PROVIDER_APP_TOKEN\", [\"secret_key\"] = \"YOUR_PROVIDER_SECRET_KEY\" },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/import-jobs/": {
      "get": {
        "summary": "Lister les tâches d'importation",
        "description": "Chaque import de l'application sous un format unique : imports et migrations de vérifications, personnes et entreprises.",
        "operationId": "get_v3_import_jobs_list",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "list_jobs",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "sessions",
                "users",
                "businesses"
              ],
              "default": "all"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tâches d'importation, les plus récentes en premier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ImportJobSummary"
                      }
                    },
                    "counts": {
                      "type": "object",
                      "properties": {
                        "all": {
                          "type": "integer"
                        },
                        "running_and_waiting": {
                          "type": "integer"
                        },
                        "needs_attention": {
                          "type": "integer"
                        },
                        "done": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.list_jobs()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.listJobs();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.ListJobs(ctx, didit.SessionsImportsListJobsParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().listJobs();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->listJobs();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.list_jobs\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.ListJobsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/import-jobs/active/": {
      "get": {
        "summary": "Lister les tâches d'importation actives",
        "description": "Ce qui est en cours d'exécution ou en attente, ainsi que ce qui vient de se terminer, pour un indicateur de progression.",
        "operationId": "get_v3_import_jobs_active",
        "x-didit-sdk": {
          "resource": "sessions.imports",
          "method": "list_active_jobs",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "responses": {
          "200": {
            "description": "Tâches d'importation actives.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ImportJobSummary"
                      }
                    },
                    "running": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Clé API manquante, invalide ou révoquée, ou l'appelant ne peut pas importer de vérifications pour cette application.",
            "content": {
              "application/json": {
                "examples": {
                  "Forbidden": {
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.imports.list_active_jobs()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.imports.listActiveJobs();\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.Imports.ListActiveJobs(ctx)\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().imports().listActiveJobs();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->imports->listActiveJobs();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.imports.list_active_jobs\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.Imports.ListActiveJobsAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/organization/{organization_id}/application/{application_id}/transactions/delete/": {
      "delete": {
        "summary": "Supprimer des transactions par lot",
        "description": "Supprimez définitivement une ou plusieurs transactions. Sélectionnez-les avec `transaction_uuids`, ou supprimez chaque transaction de l'application avec `delete_all: true`.\n\nUne transaction supprimée disparaît avec les enregistrements qui lui sont propres : ses parties, tags, notes, liens de moyen de paiement, documents et chaque version stockée de leurs fichiers, exécutions de règles, alertes, résultats de fournisseurs, instantané de réseau et données Travel Rule. Les dossiers, personnes et entreprises sont conservés ; leur lien vers la transaction supprimée est effacé. Les projets de rapports réglementaires cessent de l'inclure et sont reconstruits sans elle. La suppression est définitive et irréversible ; il n'existe aucun endpoint d'annulation.\n\nSi l'une des transactions sélectionnées figure dans un rapport réglementaire finalisé, l'ensemble de la requête est refusé avec l'erreur `409` et rien n'est supprimé. Le corps utilise `code: in_filed_report` et indique chaque transaction ainsi que les rapports qui la mentionnent. Supprimez ces rapports, puis renouvelez la requête.",
        "operationId": "batch_delete_transactions",
        "x-didit-sdk": {
          "resource": "transactions",
          "method": "batch_delete",
          "auth": "api_key",
          "server": true,
          "scope": "application"
        },
        "tags": [
          "Transactions"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'organisation."
          },
          {
            "name": "application_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de l'application."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "oneOf": [
                  {
                    "title": "Selected transactions",
                    "required": [
                      "transaction_uuids"
                    ],
                    "properties": {
                      "transaction_uuids": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "description": "UUID de transaction Didit à supprimer. Requis sauf si `delete_all` est vrai.",
                        "minItems": 1
                      },
                      "delete_all": {
                        "type": "boolean",
                        "enum": [
                          false
                        ],
                        "default": false,
                        "description": "Omettez ou envoyez `false` lorsque vous sélectionnez des transactions avec `transaction_uuids`."
                      }
                    }
                  },
                  {
                    "title": "All transactions",
                    "required": [
                      "delete_all"
                    ],
                    "properties": {
                      "delete_all": {
                        "type": "boolean",
                        "enum": [
                          true
                        ],
                        "description": "Supprimer chaque transaction de l'application. `transaction_uuids` est ignoré."
                      },
                      "transaction_uuids": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "description": "Ignoré lorsque `delete_all` est true."
                      }
                    }
                  }
                ]
              },
              "examples": {
                "Selected transactions": {
                  "value": {
                    "transaction_uuids": [
                      "abcdef12-3456-7890-abcd-ef1234567890",
                      "12345678-90ab-cdef-1234-567890abcdef"
                    ]
                  }
                },
                "All transactions": {
                  "value": {
                    "delete_all": true
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl (selected transactions)",
            "source": "curl -X DELETE 'https://verification.didit.me/v3/organization/11111111-2222-3333-4444-555555555555/application/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/transactions/delete/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"transaction_uuids\": [\"abcdef12-3456-7890-abcd-ef1234567890\"]}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\nclient = Didit()\n\nclient.transactions.batch_delete(\n    body={\n        \"transaction_uuids\": [\"abcdef12-3456-7890-abcd-ef1234567890\", \"12345678-90ab-cdef-1234-567890abcdef\"],\n    },\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nconst didit = new Didit();\n\nawait didit.transactions.batchDelete({\n  transaction_uuids: [\"abcdef12-3456-7890-abcd-ef1234567890\", \"12345678-90ab-cdef-1234-567890abcdef\"],\n});"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.TransactionsBatchDeleteParams;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nDidit client = new Didit();\n\nclient.transactions().batchDelete(TransactionsBatchDeleteParams.builder()\n        .putAdditionalProperty(\"transaction_uuids\", List.of(\"abcdef12-3456-7890-abcd-ef1234567890\", \"12345678-90ab-cdef-1234-567890abcdef\"))\n        .build());"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\n$didit = new DiditClient();\n\n$didit->transactions->batchDelete([\n    'transaction_uuids' => ['abcdef12-3456-7890-abcd-ef1234567890', '12345678-90ab-cdef-1234-567890abcdef'],\n]);"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n# and DIDIT_APPLICATION_ID.\ndidit = Didit::Client.new\n\ndidit.transactions.batch_delete(\n  body: {\n    transaction_uuids: [\"abcdef12-3456-7890-abcd-ef1234567890\", \"12345678-90ab-cdef-1234-567890abcdef\"],\n  }\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY, DIDIT_ORGANIZATION_ID\n// and DIDIT_APPLICATION_ID.\nusing var client = new DiditClient();\n\nawait client.Transactions.BatchDeleteAsync(new TransactionsBatchDeleteParams\n{\n    TransactionUuids = new string[] { \"abcdef12-3456-7890-abcd-ef1234567890\", \"12345678-90ab-cdef-1234-567890abcdef\" },\n});"
          }
        ],
        "responses": {
          "204": {
            "description": "Transactions sélectionnées supprimées."
          },
          "400": {
            "description": "Aucun sélecteur de transaction n'a été fourni.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transaction_uuids": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "example": {
                  "transaction_uuids": [
                    "This field is required unless delete_all is true."
                  ]
                }
              }
            }
          },
          "403": {
            "description": "La clé API ne peut pas supprimer de transactions. L'endpoint requiert `write:transactions`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Au moins une transaction sélectionnée figure dans un rapport réglementaire finalisé. Rien n'est supprimé.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InFiledReportError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/travel-rule/networks/": {
      "get": {
        "summary": "Obtenir les réseaux Travel Rule",
        "description": "Consultez, pour cette application, l'état réel de chaque réseau : s'il transmet via votre propre adhésion ou via celle de Didit, et la raison pour laquelle il ne peut pas encore le faire. Renvoie également le questionnaire de diligence raisonnable et vos participants. La lecture ne crée rien.",
        "operationId": "getTravelRuleNetworks",
        "x-didit-sdk": {
          "resource": "travel_rule.networks",
          "method": "retrieve",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/networks/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.networks.retrieve()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.networks.retrieve();\nconsole.log(result);"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().networks().retrieve();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->networks->retrieve();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.networks.retrieve\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Networks.RetrieveAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "États du réseau, questionnaire et participants.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleNetworksOverview"
                },
                "examples": {
                  "Before the questionnaire": {
                    "value": {
                      "platform_networks_enabled": false,
                      "questionnaire": {
                        "status": "draft",
                        "answers": {},
                        "submitted_at": null,
                        "reviewed_at": null,
                        "review_note": "",
                        "history": [],
                        "updated_at": null
                      },
                      "participants": [],
                      "networks": {
                        "gtr": {
                          "rail": "GTR",
                          "mode": "unavailable",
                          "state": "didit_onboarding",
                          "reason": "didit_membership_not_live",
                          "platform_available": false,
                          "connected": false,
                          "participant": null,
                          "vasps_reachable": 0,
                          "routed_30d": 0
                        },
                        "trust": {
                          "rail": "TRUST",
                          "mode": "unavailable",
                          "state": "unavailable",
                          "reason": "own_membership_only",
                          "platform_available": false,
                          "connected": false,
                          "participant": null,
                          "vasps_reachable": 0,
                          "routed_30d": 0
                        },
                        "verifyvasp": {
                          "rail": "VERIFYVASP",
                          "mode": "unavailable",
                          "state": "didit_onboarding",
                          "reason": "didit_membership_not_live",
                          "platform_available": false,
                          "connected": false,
                          "participant": null,
                          "vasps_reachable": 0,
                          "routed_30d": 0
                        },
                        "sygna": {
                          "rail": "SYGNA",
                          "mode": "unavailable",
                          "state": "didit_onboarding",
                          "reason": "didit_membership_not_live",
                          "platform_available": false,
                          "connected": false,
                          "participant": null,
                          "vasps_reachable": 0,
                          "routed_30d": 0
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          }
        }
      }
    },
    "/v3/travel-rule/networks/questionnaire/": {
      "get": {
        "summary": "Obtenir le questionnaire réseau",
        "description": "Lire le questionnaire de due diligence du réseau Didit pour cette application, son statut et la note d'examen de Didit. Une application qui n'en a jamais enregistré lit un brouillon vide.",
        "operationId": "getTravelRuleNetworkQuestionnaire",
        "x-didit-sdk": {
          "resource": "travel_rule.networks",
          "method": "retrieve_questionnaire",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET https://verification.didit.me/v3/travel-rule/networks/questionnaire/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.networks.retrieve_questionnaire()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.networks.retrieveQuestionnaire();\nconsole.log(result);"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().networks().retrieveQuestionnaire();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->networks->retrieveQuestionnaire();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.networks.retrieve_questionnaire\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Networks.RetrieveQuestionnaireAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le questionnaire.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleNetworkQuestionnaire"
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          }
        }
      },
      "put": {
        "summary": "Enregistrer les réponses au questionnaire réseau",
        "description": "Enregistrer les réponses au questionnaire lorsqu'il est à l'état draft ou changes_requested. Les enregistrements sont partiels : les réponses que vous n'envoyez pas sont conservées.",
        "operationId": "updateTravelRuleNetworkQuestionnaire",
        "x-didit-sdk": {
          "resource": "travel_rule.networks",
          "method": "update_questionnaire",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X PUT https://verification.didit.me/v3/travel-rule/networks/questionnaire/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"legal_name\": \"Example VASP Ltd\", \"incorporation_country\": \"ES\", \"aml_ctf_policy_attested\": true}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.networks.update_questionnaire(\n    legal_name=\"Example VASP Ltd\",\n    incorporation_country=\"ES\",\n    aml_ctf_policy_attested=True,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.networks.updateQuestionnaire({\n  legal_name: \"Example VASP Ltd\",\n  incorporation_country: \"ES\",\n  aml_ctf_policy_attested: true,\n});\nconsole.log(result);"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleNetworkQuestionnaireAnswers;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().networks().updateQuestionnaire(TravelRuleNetworkQuestionnaireAnswers.builder()\n        .legalName(\"Example VASP Ltd\")\n        .incorporationCountry(\"ES\")\n        .amlCtfPolicyAttested(true)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->networks->updateQuestionnaire([\n    'legal_name' => 'Example VASP Ltd',\n    'incorporation_country' => 'ES',\n    'aml_ctf_policy_attested' => true,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.networks.update_questionnaire(\n  legal_name: \"Example VASP Ltd\",\n  incorporation_country: \"ES\",\n  aml_ctf_policy_attested: true\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Networks.UpdateQuestionnaireAsync(new TravelRuleNetworkQuestionnaireAnswers\n{\n    LegalName = \"Example VASP Ltd\",\n    IncorporationCountry = \"ES\",\n    AmlCtfPolicyAttested = true,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleNetworkQuestionnaireAnswers"
              },
              "example": {
                "legal_name": "Example VASP Ltd",
                "incorporation_country": "ES",
                "aml_ctf_policy_attested": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Le questionnaire avec les réponses fusionnées.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleNetworkQuestionnaire"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation, indexée par champ."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "L'accès au réseau via l'adhésion Didit n'est pas encore ouvert.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "travel_rule_platform_networks_disabled"
                      ]
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Le questionnaire est auprès de Didit ou tranché : il ne peut être modifié que lorsqu'il est à l'état draft ou changes_requested.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "travel_rule_questionnaire_not_editable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/networks/questionnaire/submit/": {
      "post": {
        "summary": "Soumettre le questionnaire réseau",
        "description": "Envoyez le questionnaire enregistré pour examen par Didit. Les réponses enregistrées doivent être complètes : chaque champ sauf lei et data_protection_contact_email, avec les trois attestations définies sur true. Didit l'approuve, demande des modifications (modifiez et soumettez à nouveau) ou le rejette. Les réseaux que vous avez demandés pendant qu'il était en attente sont transmis à leur onboarding dès son approbation.",
        "operationId": "submitTravelRuleNetworkQuestionnaire",
        "x-didit-sdk": {
          "resource": "travel_rule.networks",
          "method": "submit_questionnaire",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/networks/questionnaire/submit/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.networks.submit_questionnaire()\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.networks.submitQuestionnaire();\nconsole.log(result);"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().networks().submitQuestionnaire();\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->networks->submitQuestionnaire();\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.networks.submit_questionnaire\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Networks.SubmitQuestionnaireAsync();\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le questionnaire soumis.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleNetworkQuestionnaire"
                }
              }
            }
          },
          "400": {
            "description": "Les réponses enregistrées sont incomplètes ou invalides, indexées par champ."
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "L'accès au réseau via l'adhésion Didit n'est pas encore ouvert.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "travel_rule_platform_networks_disabled"
                      ]
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Le questionnaire est auprès de Didit ou tranché : il ne peut être modifié que lorsqu'il est à l'état draft ou changes_requested.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "travel_rule_questionnaire_not_editable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/networks/{network}/request/": {
      "post": {
        "summary": "Demander un réseau Travel Rule",
        "description": "Demander le participant propre à cette application sur un réseau auquel l'adhésion de Didit donne accès (GTR ou Sygna). Sans questionnaire approuvé, le participant l'attend (questionnaire_pending) ; avec un questionnaire approuvé, il passe à l'onboarding du réseau (submitted_to_network) et devient actif dès que le réseau lui attribue un code. Idempotent : un participant en attente, en cours d'onboarding ou actif est renvoyé inchangé. Si le réseau a refusé l'inscription (last_error est défini), effectuer à nouveau la demande réessaie. TRUST et VerifyVASP ne sont accessibles que par votre propre adhésion : TRUST admet des membres par VASP, et une enclave VerifyVASP dessert un seul identifiant VASP.",
        "operationId": "requestTravelRuleNetworkAccess",
        "x-didit-sdk": {
          "resource": "travel_rule.networks",
          "method": "request_access",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "network",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "gtr",
                "sygna"
              ]
            },
            "description": "Le réseau à rejoindre via l'adhésion de Didit."
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/networks/gtr/request/ \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.networks.request_access(\n    \"your-network\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.networks.requestAccess(\"your-network\");\nconsole.log(result);"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().networks().requestAccess(\"your-network\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->networks->requestAccess('your-network');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.networks.request_access(\"your-network\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.Networks.RequestAccessAsync(\"your-network\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Votre participant sur le réseau.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleNetworkParticipant"
                }
              }
            }
          },
          "400": {
            "description": "Réseau inconnu, réseau non pris en charge par Didit (connectez votre propre adhésion), ou application sandbox.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "travel_rule_network_own_membership_only",
                        "travel_rule_network_sandbox_application"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clé API manquante ou invalide."
          },
          "403": {
            "description": "L'accès au réseau via l'adhésion Didit n'est pas encore ouvert.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "travel_rule_platform_networks_disabled"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v3/address-validation/": {
      "post": {
        "summary": "Valider une adresse",
        "description": "Confirmez qu'une adresse existe et recevez-la normalisée : ses lignes de livraison, ses composants et ses coordonnées. Cela confirme uniquement l'adresse ; cela ne lie jamais l'adresse à une personne.\n\n**Requête.** Envoyez l'adresse sur une seule ligne (`address`) ou sous forme de champs structurés (`address_line_1` et, facultativement, `address_line_2`, `city`, `region`, `postal_code`), jamais les deux, et toujours son `country` (ISO 3166-1 alpha-2 ou alpha-3).\n\n**Résultat.** `address_validation.status` est `verified` (confirmée jusqu'au bâtiment), `partially_verified` (confirmée uniquement jusqu'à la rue ou au-dessus), `not_verified` (seule la région ou la ville correspondait, ou rien ne correspondait) ou `unavailable` (la validation n'a pas pu être exécutée). Le statut HTTP est `200` pour chaque requête terminée, y compris `unavailable` ; réessayez ultérieurement en cas de résultat `unavailable`.\n\n**Facturation.** Un appel en production coûte $0.10 par adresse validée. Un résultat `unavailable` n'est pas facturé. Rien n'est stocké en dehors de l'enregistrement d'utilisation : aucune session n'est créée et le résultat est renvoyé uniquement dans cette réponse.\n\n**Sandbox.** Les clés sandbox valident la requête et renvoient toujours un résultat déterministe `verified` qui reprend l'adresse envoyée, sans consommer de crédits.\n\n**Authentification.** Envoyez la clé API de votre application dans `x-api-key`. Des identifiants manquants ou invalides renvoient `403` - cette API ne renvoie jamais `401`.\n\n**Limite de débit.** Budget d'écriture partagé de 300 requêtes par minute par clé API sur l'ensemble des endpoints POST/PATCH/DELETE (les créations de transactions et l'ingestion d'événements disposent d'un budget distinct de 600).",
        "operationId": "post_v3_address_validation",
        "x-didit-sdk": {
          "resource": "address_validation",
          "method": "validate",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Standalone APIs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/address-validation/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"address_line_1\": \"1600 Amphitheatre Pkwy\",\n    \"city\": \"Mountain View\",\n    \"region\": \"CA\",\n    \"postal_code\": \"94043\",\n    \"country\": \"US\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.address_validation.validate(\n    address_line_1=\"1600 Amphitheatre Pkwy\",\n    city=\"Mountain View\",\n    region=\"CA\",\n    postal_code=\"94043\",\n    country=\"US\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.addressValidation.validate({\n  address_line_1: \"1600 Amphitheatre Pkwy\",\n  city: \"Mountain View\",\n  region: \"CA\",\n  postal_code: \"94043\",\n  country: \"US\",\n});\nconsole.log(result);"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.AddressValidationRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.addressValidation().validate(AddressValidationRequest.builder()\n        .addressLine1(\"1600 Amphitheatre Pkwy\")\n        .city(\"Mountain View\")\n        .region(\"CA\")\n        .postalCode(\"94043\")\n        .country(\"US\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->addressValidation->validate([\n    'address_line_1' => '1600 Amphitheatre Pkwy',\n    'city' => 'Mountain View',\n    'region' => 'CA',\n    'postal_code' => '94043',\n    'country' => 'US',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.address_validation.validate(\n  address_line_1: \"1600 Amphitheatre Pkwy\",\n  city: \"Mountain View\",\n  region: \"CA\",\n  postal_code: \"94043\",\n  country: \"US\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.AddressValidation.ValidateAsync(new AddressValidationRequest\n{\n    AddressLine1 = \"1600 Amphitheatre Pkwy\",\n    City = \"Mountain View\",\n    Region = \"CA\",\n    PostalCode = \"94043\",\n    Country = \"US\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddressValidationRequest"
              },
              "examples": {
                "Structured": {
                  "summary": "Champs d'adresse structurée",
                  "value": {
                    "address_line_1": "1600 Amphitheatre Pkwy",
                    "city": "Mountain View",
                    "region": "CA",
                    "postal_code": "94043",
                    "country": "US"
                  }
                },
                "One line": {
                  "summary": "L'adresse complète sur une seule ligne",
                  "value": {
                    "address": "Paseo de la Castellana 259, 28046 Madrid",
                    "country": "ES"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "La validation est terminée. Consultez `address_validation.status` ; le code HTTP est toujours `200` pour une requête terminée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddressValidationResponse"
                },
                "examples": {
                  "Verified": {
                    "summary": "Une adresse réelle, confirmée au niveau du bâtiment",
                    "value": {
                      "request_id": "6f7d2c1e-1c5a-4a1e-9b8f-2a1f0f4b9c3d",
                      "address_validation": {
                        "status": "verified",
                        "verification_level": "premise",
                        "address": {
                          "address_line_1": "1600 Amphitheatre Pkwy",
                          "address_line_2": null,
                          "city": "Mountain View",
                          "region": "CA",
                          "postal_code": "94043-1351",
                          "country": "US"
                        },
                        "formatted_address": "1600 Amphitheatre Pkwy, Mountain View CA 94043-1351",
                        "latitude": 37.422022,
                        "longitude": -122.08429
                      },
                      "created_at": "2026-10-27T11:20:00.000000+00:00"
                    }
                  },
                  "Not verified": {
                    "summary": "Une rue inventée : seule la ville correspondait",
                    "value": {
                      "request_id": "0b9e3f4a-6c2d-4e8b-a1f7-5d3c2b1a0e9f",
                      "address_validation": {
                        "status": "not_verified",
                        "verification_level": "locality",
                        "address": {
                          "address_line_1": "Calle Inventada Que No Existe 99999 28046",
                          "address_line_2": null,
                          "city": "Madrid",
                          "region": "Madrid",
                          "postal_code": null,
                          "country": "ES"
                        },
                        "formatted_address": "Calle Inventada Que No Existe 99999 28046, Madrid, MADRID, SPAIN",
                        "latitude": 40.42603054,
                        "longitude": -3.68645331
                      },
                      "created_at": "2026-10-27T11:21:00.000000+00:00"
                    }
                  },
                  "Unavailable": {
                    "summary": "La validation n'a pas pu être exécutée ; non facturée",
                    "value": {
                      "request_id": "3c1b2a0f-9e8d-4c7b-b6a5-1f0e9d8c7b6a",
                      "address_validation": {
                        "status": "unavailable",
                        "verification_level": null,
                        "address": null,
                        "formatted_address": null,
                        "latitude": null,
                        "longitude": null
                      },
                      "created_at": "2026-10-27T11:22:00.000000+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AddressValidationValidationError"
          },
          "403": {
            "$ref": "#/components/responses/AddressValidationPermissionDenied"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitedWrite"
          }
        }
      }
    },
    "/v3/travel-rule/wallet-proofs/": {
      "get": {
        "summary": "Lister les preuves de portefeuille par capture d'écran à examiner",
        "description": "Votre file d'attente d'examen des preuves de propriété de portefeuille par capture d'écran. Une capture d'écran est la seule preuve que Didit ne peut pas vérifier lui-même : dès que l'utilisateur final la téléverse depuis le widget, elle reste PENDING jusqu'à ce que vous l'approuviez ou la rejetiez via POST /v3/travel-rule/wallet-proofs/{proof_uuid}/decision/. Les plus anciennes en premier, afin de traiter la file d'attente à partir de la preuve qui attend depuis le plus longtemps. Seules les captures d'écran téléversées apparaissent, jamais une preuve pour laquelle l'utilisateur final n'a pas encore téléversé de fichier, ni une preuve associée à un portefeuille que vous avez supprimé de votre carnet d'adresses (Didit clôture ces dernières avec l'état OWNERSHIP_CHANGED).",
        "operationId": "listTravelRuleWalletProofs",
        "x-didit-sdk": {
          "resource": "travel_rule.wallet_proofs",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Quelles preuves lister. Vaut par défaut PENDING, celles qui restent à trancher.",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "VERIFIED",
                "REJECTED",
                "EXPIRED"
              ],
              "default": "PENDING"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://verification.didit.me/v3/travel-rule/wallet-proofs/?status=PENDING \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.travel_rule.wallet_proofs.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.travelRule.walletProofs.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.travelRule().walletProofs().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->travelRule->walletProofs->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.travel_rule.wallet_proofs.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.TravelRule.WalletProofs.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Preuves par capture d'écran paginées. Le décompte est exact jusqu'à 100 et plafonné à 100 au-delà.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TravelRuleWalletProofReview"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Statut inconnu."
          },
          "401": {
            "description": "x-api-key manquant ou invalide."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les transactions."
          }
        }
      }
    },
    "/v3/travel-rule/wallet-proofs/{proof_uuid}/decision/": {
      "post": {
        "summary": "Approuver ou rejeter une capture d'écran comme preuve de portefeuille",
        "description": "Prendre une décision sur une preuve par capture d'écran depuis votre file d'attente d'examen. approve vérifie la preuve ainsi que l'entrée du carnet d'adresses et applique l'actionnariat au transfert pour lequel la session de widget a été générée, exactement comme le fait une signature vérifiée. Une capture d'écran ne confirme jamais un transfert qu'un autre client Didit a envoyé via le canal INTERNAL : cela nécessite un message signé ou un dépôt de test. reject clôture la preuve avec le statut REJECTED et failure_reason REVIEW_REJECTED ; l'utilisateur final peut recommencer une nouvelle preuve depuis le widget. La note est conservée avec la preuve.",
        "operationId": "decideTravelRuleWalletProof",
        "x-didit-sdk": {
          "resource": "travel_rule.wallet_proofs",
          "method": "decide",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "proof_uuid",
            "in": "path",
            "required": true,
            "description": "proof_id issu de la file d'attente d'examen.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleWalletProofDecision"
              },
              "example": {
                "decision": "approve",
                "note": "Address matches the wallet app."
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/wallet-proofs/{proof_uuid}/decision/ \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"decision\": \"approve\", \"note\": \"Address matches the wallet app.\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.wallet_proofs.decide(\n    \"11111111-2222-3333-4444-555555555555\",\n    decision=\"approve\",\n    note=\"Address matches the wallet app.\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.walletProofs.decide(\"11111111-2222-3333-4444-555555555555\", {\n  decision: \"approve\",\n  note: \"Address matches the wallet app.\",\n});\nconsole.log(result);"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleWalletProofDecision;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().walletProofs().decide(\"11111111-2222-3333-4444-555555555555\", TravelRuleWalletProofDecision.builder()\n        .decision(TravelRuleWalletProofDecision.Decision.of(\"approve\"))\n        .note(\"Address matches the wallet app.\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->walletProofs->decide('11111111-2222-3333-4444-555555555555', [\n    'decision' => 'approve',\n    'note' => 'Address matches the wallet app.',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.wallet_proofs.decide(\n  \"11111111-2222-3333-4444-555555555555\",\n  decision: \"approve\",\n  note: \"Address matches the wallet app.\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.WalletProofs.DecideAsync(\"11111111-2222-3333-4444-555555555555\", new TravelRuleWalletProofDecision\n{\n    Decision = \"approve\",\n    Note = \"Address matches the wallet app.\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "Le justificatif faisant l'objet de la décision.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWalletProofReview"
                }
              }
            }
          },
          "400": {
            "description": "Décision non valide, ou note de plus de 512 caractères."
          },
          "401": {
            "description": "x-api-key manquant ou invalide."
          },
          "403": {
            "description": "L'appelant ne dispose pas de l'autorisation requise pour les transactions."
          },
          "404": {
            "description": "Aucune preuve de capture d'écran soumise avec cet id dans votre application."
          },
          "409": {
            "description": "La décision relative à la preuve a déjà été prise (le corps contient son statut), ou code OWNERSHIP_CHANGED : le titulaire du portefeuille a changé ou le portefeuille a été supprimé après la création de la session du widget, la preuve est donc fermée et le titulaire actuel en nécessite une nouvelle.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofError"
                }
              }
            }
          }
        }
      }
    },
    "/v3/travel-rule/widget/{token}/proofs/": {
      "post": {
        "summary": "Démarrer une preuve de propriété du portefeuille",
        "description": "Endpoint public indexé par le token de session du widget, aucune clé API requise : le widget hébergé l'appelle lorsque l'utilisateur final choisit une méthode de preuve. Une preuve n'existe et ne compte dans votre entonnoir de preuves qu'à partir de cet appel. Choisir à nouveau la même méthode renvoie la preuve déjà ouverte (200, même challenge ou montant de dépôt) au lieu d'en démarrer une deuxième ; choisir une autre méthode ferme celle non terminée avec METHOD_SWITCHED, à l'exception d'une capture d'écran soumise ou d'un dépôt test toujours en cours de vérification. MESSAGE_SIGNING renvoie le challenge à signer ; SATOSHI_TEST l'adresse de dépôt, le montant exact et la fenêtre temporelle ; SELF_DECLARATION est vérifiée immédiatement (statut VERIFIED). Formats de signature vérifiés par famille de chaînes : les chaînes EVM acceptent une signature personal_sign (EIP-191), encodée en hexadécimal ; Bitcoin accepte une signature signmessage BIP-137 (adresses P2PKH, P2SH-P2WPKH et P2WPKH) ou une signature simple BIP-322 (adresses P2WPKH et P2TR), encodée en base64 ; Solana accepte une signature Ed25519 sur le challenge, encodée en base58 ; Tron accepte une signature signMessageV2 (TIP-191), encodée en hexadécimal. Une signature BIP-322 complète ou de justificatif de fonds, ou une adresse multisig, échoue avec SIGNATURE_UNSUPPORTED_SCHEME.",
        "operationId": "createTravelRuleWidgetProof",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "create_widget_proof",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "Token de session opaque renvoyé lors de la création de la session du widget.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleWidgetProofCreate"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/widget/{token}/proofs/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"method\": \"MESSAGE_SIGNING\"}'"
          }
        ],
        "responses": {
          "201": {
            "description": "Une nouvelle preuve PENDING (VERIFIED pour SELF_DECLARATION).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofSummary"
                }
              }
            }
          },
          "200": {
            "description": "La preuve déjà ouverte pour cette méthode, reprise.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofSummary"
                }
              }
            }
          },
          "400": {
            "description": "Corps non valide, portefeuille ne correspondant pas au transfert, SCREENSHOT non autorisé, ou code CHAIN_UNSUPPORTED lorsque la méthode n'est pas disponible sur la blockchain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofError"
                }
              }
            }
          },
          "403": {
            "description": "SELF_DECLARATION n'est pas autorisée pour cette application."
          },
          "404": {
            "description": "Token inconnu."
          },
          "409": {
            "description": "code OWNERSHIP_CHANGED : le détenteur du portefeuille a changé ou le portefeuille a été supprimé après la création de la session ; créez une nouvelle session pour le détenteur actuel. Renvoyé également pour SATOSHI_TEST lorsque la session n'a pas de satoshi_deposit_address, et lorsque la session n'a plus de tentatives restantes (aucun code ; le corps contient max_attempts, attempts_used et attempts_remaining à 0) : créez une nouvelle session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofError"
                }
              }
            }
          },
          "410": {
            "description": "La session a expiré."
          }
        }
      }
    },
    "/v3/travel-rule/widget/{token}/proofs/{proof_id}/verify/": {
      "post": {
        "summary": "Soumettre la preuve de détention du portefeuille",
        "description": "Endpoint public indexé par le token de session du widget, aucune clé API requise. Envoyez la preuve requise par la méthode de vérification : une signature pour MESSAGE_SIGNING, un txid pour SATOSHI_TEST (JSON), ou un fichier pour SCREENSHOT (multipart). Chaque soumission compte comme une tentative. Une signature qui échoue à la vérification, ou un dépôt qui ne correspond pas, renvoie 400 avec un code et laisse la preuve à l'état PENDING afin que l'utilisateur final puisse réessayer. Un dépôt détecté mais pas encore confirmé renvoie 200 avec le statut PENDING et fait l'objet d'une revérification automatique jusqu'à la fermeture de la fenêtre. Une capture d'écran renvoie 200 avec le statut PENDING et est placée dans votre file d'attente d'examen (GET /v3/travel-rule/wallet-proofs/). Une preuve EXPIRED ou REJECTED n'est jamais vérifiée ultérieurement : démarrez-en une nouvelle. Formats de signature vérifiés par famille de chaînes : les chaînes EVM acceptent une signature personal_sign (EIP-191), encodée en hexadécimal ; Bitcoin accepte une signature signmessage BIP-137 (adresses P2PKH, P2SH-P2WPKH et P2WPKH) ou une signature simple BIP-322 (adresses P2WPKH et P2TR), encodée en base64 ; Solana accepte une signature Ed25519 sur le challenge, encodée en base58 ; Tron accepte une signature signMessageV2 (TIP-191), encodée en hexadécimal. Une signature BIP-322 complète ou de justificatif de fonds, ou une adresse multisig, échoue avec SIGNATURE_UNSUPPORTED_SCHEME.",
        "operationId": "verifyTravelRuleWidgetProof",
        "x-didit-sdk": {
          "resource": "travel_rule",
          "method": "verify_widget_proof",
          "auth": "public",
          "server": false
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "Token de session opaque renvoyé lors de la création de la session du widget.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "proof_id",
            "in": "path",
            "required": true,
            "description": "proof_id renvoyé lors du lancement de la preuve.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "signature": {
                    "type": "string",
                    "description": "MESSAGE_SIGNING : la signature du portefeuille sur le défi de la preuve."
                  },
                  "txid": {
                    "type": "string",
                    "description": "SATOSHI_TEST : l'ID de transaction du dépôt de test."
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "SCREENSHOT : une image montrant le portefeuille dans l'application de portefeuille de l'utilisateur final."
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST https://verification.didit.me/v3/travel-rule/widget/{token}/proofs/{proof_id}/verify/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"signature\": \"0x...\"}'"
          }
        ],
        "responses": {
          "200": {
            "description": "VERIFIED, ou encore PENDING (une capture d'écran en attente d'examen, un dépôt non indexé ou pas encore confirmé, avec le code DEPOSIT_NOT_FOUND ou DEPOSIT_UNCONFIRMED).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofVerifyResult"
                }
              }
            }
          },
          "400": {
            "description": "Preuve manquante ; tentative infructueuse maintenant la preuve PENDING afin que l'utilisateur final puisse réessayer (code SIGNATURE_INVALID, SIGNATURE_UNSUPPORTED_SCHEME ou DEPOSIT_LOOKUP_FAILED) ; ou dépôt de test rejetant la preuve (code DEPOSIT_MISMATCH, DEPOSIT_STALE ou TXID_REUSED, statut REJECTED, avec le décompte des tentatives de la session) : sélectionner à nouveau une méthode démarre une nouvelle preuve tant que attempts_remaining est supérieur à 0.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofError"
                }
              }
            }
          },
          "404": {
            "description": "Token inconnu, ou aucun justificatif de ce type sur cette session."
          },
          "409": {
            "description": "code OWNERSHIP_CHANGED (la preuve est clôturée avec celui-ci) ; une preuve clôturée (REJECTED ou EXPIRED), avec son statut, le code avec lequel elle a été clôturée et le nombre de tentatives de la session : choisissez à nouveau une méthode pour démarrer une nouvelle preuve ; ou une preuve SELF_DECLARATION, qui est vérifiée dès son démarrage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofError"
                }
              }
            }
          },
          "410": {
            "description": "La session a expiré, ou code WINDOW_EXPIRED lorsque la fenêtre de test satoshi s'est fermée.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleWidgetProofError"
                }
              }
            }
          }
        }
      }
    },
    "/v3/id-verification/wallets/verifications/{request_id}/response/": {
      "post": {
        "operationId": "submit_wallet_verification_response",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "submit_verification_response",
          "auth": "api_key",
          "server": true
        },
        "description": "Portefeuilles de l'API Digital Credentials (Google Wallet) : envoyez ce que le portefeuille a renvoyé à votre page ou application pour une vérification dont la next_action est request_digital_credential. Didit le déchiffre, vérifie la signature de l'émetteur par rapport aux racines d'émetteurs de confiance, chaque valeur renvoyée par rapport à son empreinte signée, ainsi que la signature de l'appareil sur votre origine et cette requête, puis statue sur la vérification : vérifiée (facturée une fois) ou refusée avec le code d'erreur. Usage unique : une deuxième soumission renvoie la vérification décidée.",
        "summary": "Soumettre une réponse de portefeuille",
        "parameters": [
          {
            "in": "path",
            "name": "request_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Le request_id renvoyé par l'endpoint de démarrage.",
            "required": true
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiWalletDigitalCredentialResponseRequest"
              },
              "example": {
                "response": {
                  "protocol": "openid4vp-v1-signed",
                  "data": {
                    "response": "<compact JWE returned by the wallet>"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiWalletDigitalCredentialResponseRequest"
              },
              "example": {
                "response": {
                  "protocol": "openid4vp-v1-signed",
                  "data": {
                    "response": "<compact JWE returned by the wallet>"
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiWalletDigitalCredentialResponseRequest"
              },
              "example": {
                "response": {
                  "protocol": "openid4vp-v1-signed",
                  "data": {
                    "response": "<compact JWE returned by the wallet>"
                  }
                }
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "google_wallet",
                      "name": "Google Wallet",
                      "issuing_authority": "Google Wallet (ID pass) and US state issuers (mobile driving licence)"
                    },
                    "country": "USA",
                    "status": "Approved",
                    "outcome": "verified",
                    "error": null,
                    "interaction": "digital_credentials",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": null,
                    "identity": {
                      "full_name": "Alex Example",
                      "first_name": "Alex",
                      "last_name": "Example",
                      "date_of_birth": "1990-01-31",
                      "nationality": "USA",
                      "issuing_state": "USA"
                    },
                    "attributes": {
                      "document_number": "X0000000",
                      "document_expiry_date": "2030-01-31"
                    },
                    "level_of_assurance": "substantial",
                    "verified_at": "2026-01-01T10:01:00Z",
                    "signature_valid": true,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiClientCredentialsForbiddenErrorMessage"
                }
              }
            },
            "description": "Identifiants manquants (x-api-key ou Authorization: Bearer)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur not_found : aucune vérification de portefeuille de cette application ne possède ce request_id."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]})."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur not_a_digital_credentials_wallet : cette vérification n'accepte pas de réponse de portefeuille."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas vérifier le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/verifications/REQUEST_ID/response/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"response\": {\n    \"protocol\": \"openid4vp-v1-signed\",\n    \"data\": {\n      \"response\": \"<compact JWE returned by the wallet>\"\n    }\n  }\n}'"
          }
        ]
      }
    },
    "/v3/id-verification/wallets/google-wallet/": {
      "post": {
        "operationId": "start_google_wallet_wallet_verification",
        "x-didit-sdk": {
          "resource": "id_wallets",
          "method": "start_google_wallet",
          "auth": "api_key",
          "server": true
        },
        "description": "Démarrez une connexion Google Wallet (Google Wallet (pass d'identité) et émetteurs des États américains (permis de conduire mobile) ; USA, GBR, BRA, SGP, TWN) sans aucun workflow. Facturé une seule fois, uniquement lorsque l'identité est vérifiée. La réponse contient next_action.type=request_digital_credential avec une requête que Didit a signée pour votre application, utilisable uniquement depuis origin. Lors d'un geste de l'utilisateur depuis cette origine, transmettez next_action.digital_credentials.request à navigator.credentials.get({digital: ...}) (ou à Android Credential Manager sous la forme GetDigitalCredentialOption requestJson), puis envoyez en POST ce que le portefeuille renvoie à /v3/id-verification/wallets/verifications/{request_id}/response/. Le navigateur propose son propre QR code lorsque le portefeuille se trouve sur un autre appareil. Les applications en sandbox reçoivent une simulation déterministe (simulated: true) qui ne contacte jamais le fournisseur.",
        "summary": "Démarrer la vérification Google Wallet",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "description": "Clé de sécurité pour les réessais optionnelle (255 caractères maximum). Réessayer avec la même clé, le même portefeuille et le même corps renvoie la vérification d'origine sans démarrer une deuxième connexion ; la même clé avec un autre portefeuille ou un autre corps renvoie 409 idempotency_key_reused."
          }
        ],
        "tags": [
          "Digital ID wallets"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGoogleWalletWalletVerificationStartRequest"
              },
              "example": {
                "country": "USA",
                "vendor_data": "your-customer-reference",
                "metadata": {
                  "reference": "example"
                },
                "origin": "https://app.example.com"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGoogleWalletWalletVerificationStartRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DigitalIdWalletApiGoogleWalletWalletVerificationStartRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResponse"
                },
                "example": {
                  "request_id": "00000000-0000-4000-8000-000000000001",
                  "wallet_verification": {
                    "wallet": {
                      "id": "google_wallet",
                      "name": "Google Wallet",
                      "issuing_authority": "Google Wallet (ID pass) and US state issuers (mobile driving licence)"
                    },
                    "country": "USA",
                    "status": "Not Finished",
                    "outcome": "pending",
                    "error": null,
                    "interaction": "digital_credentials",
                    "simulated": false,
                    "expires_at": "2026-01-01T10:10:00Z",
                    "next_action": {
                      "type": "request_digital_credential",
                      "digital_credentials": {
                        "protocol": "openid4vp-v1-signed",
                        "request": {
                          "requests": [
                            {
                              "protocol": "openid4vp-v1-signed",
                              "data": {
                                "request": "<compact JWS signed by Didit>"
                              }
                            }
                          ]
                        }
                      }
                    },
                    "identity": null,
                    "attributes": null,
                    "level_of_assurance": null,
                    "verified_at": null,
                    "signature_valid": null,
                    "credential_type": "person_identification"
                  },
                  "vendor_data": "your-customer-reference",
                  "metadata": {
                    "reference": "example"
                  },
                  "created_at": "2026-01-01T10:00:00Z"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartBadRequest"
                }
              }
            },
            "description": "Erreurs de validation de champ ({field: [messages]}), ou erreur return_url_invalid, return_url_not_allowed, origin_invalid, origin_not_allowed, invalid_personal_code, invalid_phone_number ou idempotency_key_invalid."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationStartForbidden"
                }
              }
            },
            "description": "Identifiants manquants ({detail}), ou erreur wallet_unavailable, insufficient_credits ou contract_rate_missing."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur idempotency_key_reused ou idempotency_key_in_progress (avec Retry-After)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_provider_unavailable : le fournisseur n'a pas pu démarrer ; rien n'a été créé."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
                }
              }
            },
            "description": "erreur wallet_not_configured : cet environnement ne peut pas joindre le portefeuille."
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request POST \\\n  --url https://verification.didit.me/v3/id-verification/wallets/google-wallet/ \\\n  --header 'x-api-key: YOUR_API_KEY' \\\n  --header 'Idempotency-Key: your-unique-attempt-key' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"country\": \"USA\",\n  \"vendor_data\": \"your-customer-reference\",\n  \"metadata\": {\n    \"reference\": \"example\"\n  },\n  \"origin\": \"https://app.example.com\"\n}'"
          }
        ],
        "x-didit-wallet-id": "google_wallet"
      }
    },
    "/v3/session/{sessionId}/kyb/documents/": {
      "post": {
        "summary": "Téléverser des documents KYB pour une session",
        "description": "Téléversez un ou plusieurs documents d'entreprise (statuts, registre des actionnaires, extrait Kbis/certificat d'immatriculation, ...) vers l'étape Documents KYB d'une session de Vérification d'entreprise, depuis votre propre serveur au lieu de la page hébergée. Didit exécute le pipeline hébergé : compression, OCR, contrôles d'altération et de cohérence inter-documents, regroupement documentaire, et fait avancer la session lorsque les groupes de documents requis sont satisfaits. L'étape coûte un tarif forfaitaire unique, quel que soit le nombre de fichiers envoyés. La session doit être ouverte et à l'étape Documents KYB, et l'entreprise choisie à l'étape du registre doit exister. Consultez les personnes nommées dans les documents avec `GET /v3/session/{sessionId}/kyb/extracted-parties/`. Nécessite `write:businesses`.",
        "operationId": "post_v3_session_kyb_documents",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "upload_kyb_documents",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification d'entreprise (KYB). Il doit appartenir à l'application de la clé API.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud de workflow de l'étape KYB. Nécessaire uniquement lorsque le workflow comporte plus d'un nœud KYB ; par défaut, Didit utilise le nœud propre à la session.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "documents"
                ],
                "properties": {
                  "documents": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Fichiers à téléverser : JPG, JPEG, PNG, TIFF, WEBP, PDF ou archives ZIP de ceux-ci. PDF jusqu'à 50 MB, photos jusqu'à 6 MB avant compression."
                  },
                  "document_passwords": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Une entrée par fichier dans `documents`, dans le même ordre : le mot de passe d'un PDF protégé, vide pour tout autre fichier."
                  },
                  "document_group": {
                    "type": "string",
                    "enum": [
                      "LEGAL_PRESENCE",
                      "COMPANY_DETAILS",
                      "OWNERSHIP_STRUCTURE",
                      "REPRESENTATIVES_AUTHORIZATION"
                    ],
                    "description": "Groupe de documents requis auquel correspond ce téléversement."
                  },
                  "locale": {
                    "type": "string",
                    "maxLength": 10,
                    "description": "Locale utilisée pour traduire la réponse de l'étape suivante."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Documents traités. Lorsque chaque groupe requis est satisfait, la session avance et `next_step` indique l'étape suivante ; sinon, elle reste à l'étape Documents et `document_groups` ainsi que `document_answer` indiquent ce qui manque encore.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean"
                    },
                    "next_step": {
                      "type": "string",
                      "nullable": true,
                      "description": "Étape où se trouve la session après le téléversement."
                    },
                    "kyb_status": {
                      "type": "string",
                      "description": "Statut de la vérification de l'entreprise."
                    },
                    "document_answer": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "Résultat pour chaque document téléversé et nombre de téléversements restants."
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "valid": true,
                  "next_step": "KYB_KEY_PEOPLE",
                  "kyb_status": "In Progress"
                }
              }
            }
          },
          "400": {
            "description": "Un document a été refusé (altération, illisible ou non pris en charge) ou la session n'a pas encore d'entreprise KYB. Réessayez avec un autre fichier tant qu'il reste des tentatives.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "message": "No KYB company found. Submit company data first."
                }
              }
            }
          },
          "402": {
            "description": "L'organisation n'a plus de crédit pour l'étape des documents.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Insufficient credits."
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée, appartient à une autre application ou se trouve en dehors des limites d'une clé restreinte ; aucun détail ne permet de les distinguer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Session not found."
                }
              }
            }
          },
          "409": {
            "description": "La session est terminée (`kyb_session_not_writable`) ou n'est pas à l'étape des documents KYB (`kyb_step_mismatch`, avec `next_step` indiquant l'étape à laquelle elle se trouve).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    },
                    "code": {
                      "type": "string"
                    },
                    "next_step": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "The session is not on the step this operation completes.",
                  "code": "kyb_step_mismatch",
                  "next_step": "KYB_REGISTRY"
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 300 requêtes d'écriture (POST, PATCH, DELETE) par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/DocumentProcessingBusy"
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.upload_kyb_documents(\n    \"33333333-4444-5555-6666-777777777777\",\n    documents=[open(\"document.pdf\", \"rb\")],\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit, { fileFromPath } from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.uploadKybDocuments(\"33333333-4444-5555-6666-777777777777\", {\n  documents: [await fileFromPath(\"document.pdf\")],\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UploadKYBDocuments(ctx, \"33333333-4444-5555-6666-777777777777\", didit.SessionsUploadKYBDocumentsParams{\n\tDocuments: []didit.File{didit.FileFromPath(\"document.pdf\")},\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.nio.file.Path;\nimport java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.SessionsUploadKybDocumentsParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().uploadKybDocuments(\"33333333-4444-5555-6666-777777777777\", SessionsUploadKybDocumentsParams.builder()\n        .documents(List.of(Path.of(\"document.pdf\")))\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\nuse Didit\\File;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->uploadKybDocuments('33333333-4444-5555-6666-777777777777', [\n    'documents' => [File::fromPath('document.pdf')],\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.upload_kyb_documents(\n  \"33333333-4444-5555-6666-777777777777\",\n  documents: [Pathname(\"document.pdf\")]\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UploadKybDocumentsAsync(\"33333333-4444-5555-6666-777777777777\", new SessionsUploadKybDocumentsParams\n{\n    Documents = new FileUpload[] { FileUpload.FromPath(\"document.pdf\") },\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/kyb/extracted-parties/": {
      "get": {
        "summary": "Lister les parties mentionnées dans les documents téléversés",
        "description": "Renvoie les actionnaires et dirigeants mentionnés dans les documents téléversés pour cette session KYB, fusionnés par personne et associés aux documents qui les mentionnent. Présentez-les à votre candidat pour confirmation, puis déclarez-les avec les endpoints de brouillon de parties. Une plage reste une plage : `ownership_percent.text` conserve la valeur textuelle brute et `min` / `max` les valeurs numériques qui en ont été extraites. Personne n'est désigné comme UBO ici ; cela est déterminé lors de la soumission des parties, d'après les paramètres de rôle et les seuils d'actionnariat du workflow. La même liste est présente dans la décision de la session sous `document_verifications[].extracted_parties`. Nécessite `read:businesses` ou `read:sessions`.",
        "operationId": "get_v3_session_kyb_extracted_parties",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "list_kyb_extracted_parties",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification d'entreprise (KYB). Il doit appartenir à l'application de la clé API.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud de workflow de l'étape KYB. Nécessaire uniquement lorsque le workflow comporte plus d'un nœud KYB ; par défaut, Didit utilise le nœud propre à la session.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Parties désignées par les documents actuels.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "parties",
                    "document_count"
                  ],
                  "properties": {
                    "parties": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "entity_type": {
                            "type": "string",
                            "enum": [
                              "person",
                              "company"
                            ]
                          },
                          "first_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "appointment_date": {
                            "type": "string",
                            "nullable": true
                          },
                          "designation": {
                            "type": "string",
                            "nullable": true
                          },
                          "roles": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "role": {
                                  "type": "string",
                                  "enum": [
                                    "director",
                                    "non_executive_director",
                                    "secretary",
                                    "chairman",
                                    "ubo",
                                    "shareholder",
                                    "representative",
                                    "founder",
                                    "legal_advisor",
                                    "authorized_signatory",
                                    "trustee",
                                    "beneficiary",
                                    "settlor",
                                    "protector",
                                    "company_officer",
                                    "investor",
                                    "other"
                                  ]
                                },
                                "ownership_percent": {
                                  "type": "object",
                                  "properties": {
                                    "text": {
                                      "type": "string",
                                      "nullable": true,
                                      "description": "La valeur de l'actionnariat exactement telle qu'indiquée dans le document, comme `25-50%`, `>50%` ou `NO EXHIBE`."
                                    },
                                    "min": {
                                      "type": "number",
                                      "nullable": true,
                                      "description": "Nombre inférieur extrait de `text` ; null lorsqu'aucun n'est indiqué."
                                    },
                                    "max": {
                                      "type": "number",
                                      "nullable": true,
                                      "description": "Nombre supérieur extrait de `text` ; null lorsqu'aucun n'est mentionné."
                                    }
                                  }
                                }
                              }
                            }
                          },
                          "documents": {
                            "type": "array",
                            "description": "Les documents téléversés dans lesquels cette partie était nommée.",
                            "items": {
                              "type": "object",
                              "properties": {
                                "document_uuid": {
                                  "type": "string",
                                  "format": "uuid"
                                },
                                "document_type": {
                                  "type": "string",
                                  "nullable": true
                                },
                                "document_subtype": {
                                  "type": "string",
                                  "nullable": true
                                },
                                "original_filename": {
                                  "type": "string",
                                  "nullable": true
                                },
                                "status": {
                                  "type": "string",
                                  "nullable": true
                                }
                              }
                            }
                          }
                        }
                      },
                      "description": "Les actionnaires et dirigeants mentionnés dans les documents téléversés, fusionnés par personne. Personne n'est qualifié de UBO ici : cette décision intervient lorsque les parties sont soumises."
                    },
                    "document_count": {
                      "type": "integer",
                      "description": "Nombre de documents téléversés à partir desquels la liste a été lue."
                    },
                    "node_id": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                },
                "example": {
                  "parties": [
                    {
                      "name": "Ana Lopez",
                      "entity_type": "person",
                      "first_name": "Ana",
                      "last_name": "Lopez",
                      "appointment_date": null,
                      "designation": "Administrador unico",
                      "roles": [
                        {
                          "role": "shareholder",
                          "ownership_percent": {
                            "text": "60%",
                            "min": 60,
                            "max": 60
                          }
                        }
                      ],
                      "documents": [
                        {
                          "document_uuid": "0a3f1e2c-7c2f-4a1b-9d55-2f8d2a5d6b41",
                          "document_type": "OWNERSHIP_STRUCTURE",
                          "document_subtype": "ARTICLES_OF_INCORPORATION",
                          "original_filename": "acta_constitutiva.pdf",
                          "status": "Approved"
                        }
                      ]
                    }
                  ],
                  "document_count": 1,
                  "node_id": "node_kyb_documents"
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée, appartient à une autre application ou se trouve en dehors des limites d'une clé restreinte ; aucun détail ne permet de les distinguer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Session not found."
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.list_kyb_extracted_parties(\n    \"33333333-4444-5555-6666-777777777777\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.listKybExtractedParties(\"33333333-4444-5555-6666-777777777777\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.ListKYBExtractedParties(ctx, \"33333333-4444-5555-6666-777777777777\", didit.SessionsListKYBExtractedPartiesParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().listKybExtractedParties(\"33333333-4444-5555-6666-777777777777\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->listKybExtractedParties('33333333-4444-5555-6666-777777777777');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.list_kyb_extracted_parties(\"33333333-4444-5555-6666-777777777777\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.ListKybExtractedPartiesAsync(\"33333333-4444-5555-6666-777777777777\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/kyb/parties/drafts/": {
      "get": {
        "summary": "Lister les brouillons de parties KYB",
        "description": "Lister les parties que vous préparez pour cette session KYB, de la plus ancienne à la plus récente. Un brouillon n'est pas une partie déclarée : il n'apparaît ni dans la décision ni dans la console et ne crée aucune session de vérification tant que vous ne l'avez pas soumis avec `POST /v3/session/{sessionId}/kyb/parties/submit/`. Nécessite `write:businesses`.",
        "operationId": "get_v3_session_kyb_party_drafts",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "list_kyb_party_drafts",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification d'entreprise (KYB). Il doit appartenir à l'application de la clé API.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud de workflow de l'étape KYB. Nécessaire uniquement lorsque le workflow comporte plus d'un nœud KYB ; par défaut, Didit utilise le nœud propre à la session.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Les brouillons enregistrés.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "parties": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "draft_id",
                          "created_at",
                          "updated_at",
                          "party"
                        ],
                        "properties": {
                          "draft_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "party": {
                            "type": "object",
                            "required": [
                              "entity_type",
                              "nationality"
                            ],
                            "properties": {
                              "entity_type": {
                                "type": "string",
                                "enum": [
                                  "person",
                                  "company"
                                ],
                                "description": "Indique si la partie est un particulier ou une entreprise."
                              },
                              "full_name": {
                                "type": "string",
                                "maxLength": 255,
                                "description": "Nom complet d'une personne. Envoyez-le, ou transmettez `first_name` et `last_name`."
                              },
                              "first_name": {
                                "type": "string",
                                "maxLength": 128
                              },
                              "last_name": {
                                "type": "string",
                                "maxLength": 128
                              },
                              "role": {
                                "type": "string",
                                "enum": [
                                  "director",
                                  "non_executive_director",
                                  "secretary",
                                  "chairman",
                                  "ubo",
                                  "shareholder",
                                  "representative",
                                  "founder",
                                  "legal_advisor",
                                  "authorized_signatory",
                                  "trustee",
                                  "beneficiary",
                                  "settlor",
                                  "protector",
                                  "company_officer",
                                  "investor",
                                  "other"
                                ],
                                "description": "Rôle que détient la partie. Interchangeable avec `roles` ; lorsque les deux sont envoyés, ils sont fusionnés."
                              },
                              "roles": {
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "enum": [
                                    "director",
                                    "non_executive_director",
                                    "secretary",
                                    "chairman",
                                    "ubo",
                                    "shareholder",
                                    "representative",
                                    "founder",
                                    "legal_advisor",
                                    "authorized_signatory",
                                    "trustee",
                                    "beneficiary",
                                    "settlor",
                                    "protector",
                                    "company_officer",
                                    "investor",
                                    "other"
                                  ]
                                },
                                "description": "Chaque rôle détenu par la partie. Une personne a besoin d'au moins un rôle (ici ou dans `role`)."
                              },
                              "position": {
                                "type": "string",
                                "maxLength": 128,
                                "description": "Intitulé du poste d'une personne."
                              },
                              "date_of_birth": {
                                "type": "string",
                                "format": "date",
                                "nullable": true
                              },
                              "company_name": {
                                "type": "string",
                                "maxLength": 255,
                                "description": "Nom d'une partie représentant l'entreprise. Requis lorsque `entity_type` est `company`."
                              },
                              "registration_number": {
                                "type": "string",
                                "maxLength": 100,
                                "description": "Numéro d'immatriculation d'une partie de l'entreprise."
                              },
                              "email": {
                                "type": "string",
                                "format": "email",
                                "description": "Destination d'envoi du lien de vérification. Requis lorsque la partie doit effectuer une vérification, ce qui dépend des paramètres de rôle et des seuils d'actionnariat du workflow."
                              },
                              "ownership_percent": {
                                "type": "number",
                                "nullable": true,
                                "description": "Part de l'entreprise détenue par la partie."
                              },
                              "nationality": {
                                "type": "string",
                                "maxLength": 100,
                                "description": "Nationalité d'une personne, ou pays de constitution d'une entreprise. Obligatoire pour chaque partie."
                              },
                              "phone_number": {
                                "type": "string",
                                "maxLength": 32
                              },
                              "custom_fields": {
                                "type": "object",
                                "additionalProperties": true,
                                "description": "Champs supplémentaires définis par le workflow."
                              },
                              "skip_verification": {
                                "type": "boolean",
                                "default": false,
                                "description": "Demander d'ignorer la vérification de cette partie. Pris en compte uniquement lorsque le rôle de la partie permet de l'ignorer dans les paramètres Personnes clés du workflow."
                              }
                            }
                          }
                        }
                      }
                    },
                    "node_id": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                },
                "example": {
                  "parties": [
                    {
                      "draft_id": "5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d",
                      "created_at": "2026-10-31T10:00:00Z",
                      "updated_at": "2026-10-31T10:00:00Z",
                      "party": {
                        "entity_type": "person",
                        "first_name": "Ana",
                        "last_name": "Lopez",
                        "roles": [
                          "ubo",
                          "director"
                        ],
                        "ownership_percent": 60,
                        "nationality": "MEX",
                        "email": "ana.lopez@example.com",
                        "date_of_birth": "1984-06-12"
                      }
                    }
                  ],
                  "node_id": "node_kyb_key_people"
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée, appartient à une autre application ou se trouve en dehors des limites d'une clé restreinte ; aucun détail ne permet de les distinguer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Session not found."
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.list_kyb_party_drafts(\n    \"33333333-4444-5555-6666-777777777777\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.listKybPartyDrafts(\"33333333-4444-5555-6666-777777777777\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.ListKYBPartyDrafts(ctx, \"33333333-4444-5555-6666-777777777777\", didit.SessionsListKYBPartyDraftsParams{})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().listKybPartyDrafts(\"33333333-4444-5555-6666-777777777777\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->listKybPartyDrafts('33333333-4444-5555-6666-777777777777');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.list_kyb_party_drafts(\"33333333-4444-5555-6666-777777777777\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.ListKybPartyDraftsAsync(\"33333333-4444-5555-6666-777777777777\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "post": {
        "summary": "Créer un brouillon de partie KYB",
        "description": "Ajouter une partie (une personne ou une entreprise) à la liste que vous préparez pour cette session KYB. Les mêmes champs et règles que pour l'écran hébergé Personnes clés s'appliquent : une personne nécessite `full_name` ou `first_name` et `last_name`, au moins un rôle et une nationalité ; une entreprise nécessite `company_name` et le pays de constitution dans `nationality`. Rien n'est déclaré ni facturé avant `POST /v3/session/{sessionId}/kyb/parties/submit/`. Nécessite `write:businesses`.",
        "operationId": "post_v3_session_kyb_party_drafts",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "create_kyb_party_draft",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification d'entreprise (KYB). Il doit appartenir à l'application de la clé API.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud de workflow de l'étape KYB. Nécessaire uniquement lorsque le workflow comporte plus d'un nœud KYB ; par défaut, Didit utilise le nœud propre à la session.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "entity_type",
                  "nationality"
                ],
                "properties": {
                  "entity_type": {
                    "type": "string",
                    "enum": [
                      "person",
                      "company"
                    ],
                    "description": "Indique si la partie est un particulier ou une entreprise."
                  },
                  "full_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom complet d'une personne. Envoyez-le, ou transmettez `first_name` et `last_name`."
                  },
                  "first_name": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "last_name": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "director",
                      "non_executive_director",
                      "secretary",
                      "chairman",
                      "ubo",
                      "shareholder",
                      "representative",
                      "founder",
                      "legal_advisor",
                      "authorized_signatory",
                      "trustee",
                      "beneficiary",
                      "settlor",
                      "protector",
                      "company_officer",
                      "investor",
                      "other"
                    ],
                    "description": "Rôle que détient la partie. Interchangeable avec `roles` ; lorsque les deux sont envoyés, ils sont fusionnés."
                  },
                  "roles": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "director",
                        "non_executive_director",
                        "secretary",
                        "chairman",
                        "ubo",
                        "shareholder",
                        "representative",
                        "founder",
                        "legal_advisor",
                        "authorized_signatory",
                        "trustee",
                        "beneficiary",
                        "settlor",
                        "protector",
                        "company_officer",
                        "investor",
                        "other"
                      ]
                    },
                    "description": "Chaque rôle détenu par la partie. Une personne a besoin d'au moins un rôle (ici ou dans `role`)."
                  },
                  "position": {
                    "type": "string",
                    "maxLength": 128,
                    "description": "Intitulé du poste d'une personne."
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "nullable": true
                  },
                  "company_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom d'une partie représentant l'entreprise. Requis lorsque `entity_type` est `company`."
                  },
                  "registration_number": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Numéro d'immatriculation d'une partie de l'entreprise."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Destination d'envoi du lien de vérification. Requis lorsque la partie doit effectuer une vérification, ce qui dépend des paramètres de rôle et des seuils d'actionnariat du workflow."
                  },
                  "ownership_percent": {
                    "type": "number",
                    "nullable": true,
                    "description": "Part de l'entreprise détenue par la partie."
                  },
                  "nationality": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Nationalité d'une personne, ou pays de constitution d'une entreprise. Obligatoire pour chaque partie."
                  },
                  "phone_number": {
                    "type": "string",
                    "maxLength": 32
                  },
                  "custom_fields": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Champs supplémentaires définis par le workflow."
                  },
                  "skip_verification": {
                    "type": "boolean",
                    "default": false,
                    "description": "Demander d'ignorer la vérification de cette partie. Pris en compte uniquement lorsque le rôle de la partie permet de l'ignorer dans les paramètres Personnes clés du workflow."
                  }
                }
              },
              "example": {
                "entity_type": "person",
                "first_name": "Ana",
                "last_name": "Lopez",
                "roles": [
                  "ubo",
                  "director"
                ],
                "ownership_percent": 60,
                "nationality": "MEX",
                "email": "ana.lopez@example.com",
                "date_of_birth": "1984-06-12"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Brouillon créé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "draft_id",
                    "created_at",
                    "updated_at",
                    "party"
                  ],
                  "properties": {
                    "draft_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "party": {
                      "type": "object",
                      "required": [
                        "entity_type",
                        "nationality"
                      ],
                      "properties": {
                        "entity_type": {
                          "type": "string",
                          "enum": [
                            "person",
                            "company"
                          ],
                          "description": "Indique si la partie est un particulier ou une entreprise."
                        },
                        "full_name": {
                          "type": "string",
                          "maxLength": 255,
                          "description": "Nom complet d'une personne. Envoyez-le, ou transmettez `first_name` et `last_name`."
                        },
                        "first_name": {
                          "type": "string",
                          "maxLength": 128
                        },
                        "last_name": {
                          "type": "string",
                          "maxLength": 128
                        },
                        "role": {
                          "type": "string",
                          "enum": [
                            "director",
                            "non_executive_director",
                            "secretary",
                            "chairman",
                            "ubo",
                            "shareholder",
                            "representative",
                            "founder",
                            "legal_advisor",
                            "authorized_signatory",
                            "trustee",
                            "beneficiary",
                            "settlor",
                            "protector",
                            "company_officer",
                            "investor",
                            "other"
                          ],
                          "description": "Rôle que détient la partie. Interchangeable avec `roles` ; lorsque les deux sont envoyés, ils sont fusionnés."
                        },
                        "roles": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "director",
                              "non_executive_director",
                              "secretary",
                              "chairman",
                              "ubo",
                              "shareholder",
                              "representative",
                              "founder",
                              "legal_advisor",
                              "authorized_signatory",
                              "trustee",
                              "beneficiary",
                              "settlor",
                              "protector",
                              "company_officer",
                              "investor",
                              "other"
                            ]
                          },
                          "description": "Chaque rôle détenu par la partie. Une personne a besoin d'au moins un rôle (ici ou dans `role`)."
                        },
                        "position": {
                          "type": "string",
                          "maxLength": 128,
                          "description": "Intitulé du poste d'une personne."
                        },
                        "date_of_birth": {
                          "type": "string",
                          "format": "date",
                          "nullable": true
                        },
                        "company_name": {
                          "type": "string",
                          "maxLength": 255,
                          "description": "Nom d'une partie représentant l'entreprise. Requis lorsque `entity_type` est `company`."
                        },
                        "registration_number": {
                          "type": "string",
                          "maxLength": 100,
                          "description": "Numéro d'immatriculation d'une partie de l'entreprise."
                        },
                        "email": {
                          "type": "string",
                          "format": "email",
                          "description": "Destination d'envoi du lien de vérification. Requis lorsque la partie doit effectuer une vérification, ce qui dépend des paramètres de rôle et des seuils d'actionnariat du workflow."
                        },
                        "ownership_percent": {
                          "type": "number",
                          "nullable": true,
                          "description": "Part de l'entreprise détenue par la partie."
                        },
                        "nationality": {
                          "type": "string",
                          "maxLength": 100,
                          "description": "Nationalité d'une personne, ou pays de constitution d'une entreprise. Obligatoire pour chaque partie."
                        },
                        "phone_number": {
                          "type": "string",
                          "maxLength": 32
                        },
                        "custom_fields": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Champs supplémentaires définis par le workflow."
                        },
                        "skip_verification": {
                          "type": "boolean",
                          "default": false,
                          "description": "Demander d'ignorer la vérification de cette partie. Pris en compte uniquement lorsque le rôle de la partie permet de l'ignorer dans les paramètres Personnes clés du workflow."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "draft_id": "5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d",
                  "created_at": "2026-10-31T10:00:00Z",
                  "updated_at": "2026-10-31T10:00:00Z",
                  "party": {
                    "entity_type": "person",
                    "first_name": "Ana",
                    "last_name": "Lopez",
                    "roles": [
                      "ubo",
                      "director"
                    ],
                    "ownership_percent": 60,
                    "nationality": "MEX",
                    "email": "ana.lopez@example.com",
                    "date_of_birth": "1984-06-12"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Un champ de partie prenante est invalide ou un champ obligatoire est manquant.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "non_field_errors": [
                    "Person parties require at least one role."
                  ]
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée, appartient à une autre application ou se trouve en dehors des limites d'une clé restreinte ; aucun détail ne permet de les distinguer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Session not found."
                }
              }
            }
          },
          "409": {
            "description": "La session est terminée (`kyb_session_not_writable`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "This verification session is no longer accepting changes.",
                  "code": "kyb_session_not_writable"
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 300 requêtes d'écriture (POST, PATCH, DELETE) par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.create_kyb_party_draft(\n    \"33333333-4444-5555-6666-777777777777\",\n    entity_type=\"person\",\n    first_name=\"Ana\",\n    last_name=\"Lopez\",\n    roles=[\"ubo\", \"director\"],\n    date_of_birth=\"1984-06-12\",\n    email=\"ana.lopez@example.com\",\n    ownership_percent=60.0,\n    nationality=\"MEX\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.createKybPartyDraft(\"33333333-4444-5555-6666-777777777777\", {\n  entity_type: \"person\",\n  first_name: \"Ana\",\n  last_name: \"Lopez\",\n  roles: [\"ubo\", \"director\"],\n  date_of_birth: \"1984-06-12\",\n  email: \"ana.lopez@example.com\",\n  ownership_percent: 60.0,\n  nationality: \"MEX\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.CreateKYBPartyDraft(ctx, \"33333333-4444-5555-6666-777777777777\", didit.SessionsCreateKYBPartyDraftParams{\n\tEntityType:       \"person\",\n\tFirstName:        didit.String(\"Ana\"),\n\tLastName:         didit.String(\"Lopez\"),\n\tRoles:            didit.Some([]didit.SessionsCreateKYBPartyDraftParamsRoles{\"ubo\", \"director\"}),\n\tDateOfBirth:      didit.String(\"1984-06-12\"),\n\tEmail:            didit.String(\"ana.lopez@example.com\"),\n\tOwnershipPercent: didit.Float(60.0),\n\tNationality:      \"MEX\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import java.time.LocalDate;\nimport java.util.List;\nimport me.didit.Didit;\nimport me.didit.types.SessionsCreateKybPartyDraftParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().createKybPartyDraft(\"33333333-4444-5555-6666-777777777777\", SessionsCreateKybPartyDraftParams.builder()\n        .entityType(SessionsCreateKybPartyDraftParams.EntityType.of(\"person\"))\n        .firstName(\"Ana\")\n        .lastName(\"Lopez\")\n        .roles(List.of(SessionsCreateKybPartyDraftParams.Roles.of(\"ubo\"), SessionsCreateKybPartyDraftParams.Roles.of(\"director\")))\n        .dateOfBirth(LocalDate.parse(\"1984-06-12\"))\n        .email(\"ana.lopez@example.com\")\n        .ownershipPercent(60.0)\n        .nationality(\"MEX\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->createKybPartyDraft('33333333-4444-5555-6666-777777777777', [\n    'entity_type' => 'person',\n    'first_name' => 'Ana',\n    'last_name' => 'Lopez',\n    'roles' => ['ubo', 'director'],\n    'date_of_birth' => '1984-06-12',\n    'email' => 'ana.lopez@example.com',\n    'ownership_percent' => 60.0,\n    'nationality' => 'MEX',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.create_kyb_party_draft(\n  \"33333333-4444-5555-6666-777777777777\",\n  entity_type: \"person\",\n  first_name: \"Ana\",\n  last_name: \"Lopez\",\n  roles: [\"ubo\", \"director\"],\n  date_of_birth: \"1984-06-12\",\n  email: \"ana.lopez@example.com\",\n  ownership_percent: 60.0,\n  nationality: \"MEX\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.CreateKybPartyDraftAsync(\"33333333-4444-5555-6666-777777777777\", new SessionsCreateKybPartyDraftParams\n{\n    EntityType = \"person\",\n    FirstName = \"Ana\",\n    LastName = \"Lopez\",\n    Roles = new SessionsCreateKybPartyDraftParamsRoles[] { \"ubo\", \"director\" },\n    DateOfBirth = \"1984-06-12\",\n    Email = \"ana.lopez@example.com\",\n    OwnershipPercent = 60.0,\n    Nationality = \"MEX\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/kyb/parties/drafts/{draftId}/": {
      "patch": {
        "summary": "Modifier un brouillon de partie KYB",
        "description": "Modifier les champs d'un brouillon de partie prenante. La modification est fusionnée dans le brouillon stocké et la partie prenante fusionnée est validée dans son ensemble, de sorte qu'une modification qui laisserait la partie prenante incomplète est rejetée. La modification de `first_name` ou de `last_name` remplace le nom complet stocké. Nécessite `write:businesses`.",
        "operationId": "patch_v3_session_kyb_party_draft",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "update_kyb_party_draft",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification d'entreprise (KYB). Il doit appartenir à l'application de la clé API.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "draftId",
            "in": "path",
            "required": true,
            "description": "UUID du brouillon de la partie (`draft_id` renvoyé lors de sa création).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud de workflow de l'étape KYB. Nécessaire uniquement lorsque le workflow comporte plus d'un nœud KYB ; par défaut, Didit utilise le nœud propre à la session.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Tout sous-ensemble des champs de la partie. La modification est fusionnée dans le brouillon enregistré et la partie fusionnée est validée dans son ensemble, de sorte qu'un brouillon qui pouvait être soumis avant une modification peut toujours l'être après celle-ci.",
                "properties": {
                  "entity_type": {
                    "type": "string",
                    "enum": [
                      "person",
                      "company"
                    ],
                    "description": "Indique si la partie est un particulier ou une entreprise."
                  },
                  "full_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom complet d'une personne. Envoyez-le, ou transmettez `first_name` et `last_name`."
                  },
                  "first_name": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "last_name": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "director",
                      "non_executive_director",
                      "secretary",
                      "chairman",
                      "ubo",
                      "shareholder",
                      "representative",
                      "founder",
                      "legal_advisor",
                      "authorized_signatory",
                      "trustee",
                      "beneficiary",
                      "settlor",
                      "protector",
                      "company_officer",
                      "investor",
                      "other"
                    ],
                    "description": "Rôle que détient la partie. Interchangeable avec `roles` ; lorsque les deux sont envoyés, ils sont fusionnés."
                  },
                  "roles": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "director",
                        "non_executive_director",
                        "secretary",
                        "chairman",
                        "ubo",
                        "shareholder",
                        "representative",
                        "founder",
                        "legal_advisor",
                        "authorized_signatory",
                        "trustee",
                        "beneficiary",
                        "settlor",
                        "protector",
                        "company_officer",
                        "investor",
                        "other"
                      ]
                    },
                    "description": "Chaque rôle détenu par la partie. Une personne a besoin d'au moins un rôle (ici ou dans `role`)."
                  },
                  "position": {
                    "type": "string",
                    "maxLength": 128,
                    "description": "Intitulé du poste d'une personne."
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "nullable": true
                  },
                  "company_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom d'une partie représentant l'entreprise. Requis lorsque `entity_type` est `company`."
                  },
                  "registration_number": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Numéro d'immatriculation d'une partie de l'entreprise."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Destination d'envoi du lien de vérification. Requis lorsque la partie doit effectuer une vérification, ce qui dépend des paramètres de rôle et des seuils d'actionnariat du workflow."
                  },
                  "ownership_percent": {
                    "type": "number",
                    "nullable": true,
                    "description": "Part de l'entreprise détenue par la partie."
                  },
                  "nationality": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Nationalité d'une personne, ou pays de constitution d'une entreprise. Obligatoire pour chaque partie."
                  },
                  "phone_number": {
                    "type": "string",
                    "maxLength": 32
                  },
                  "custom_fields": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Champs supplémentaires définis par le workflow."
                  },
                  "skip_verification": {
                    "type": "boolean",
                    "default": false,
                    "description": "Demander d'ignorer la vérification de cette partie. Pris en compte uniquement lorsque le rôle de la partie permet de l'ignorer dans les paramètres Personnes clés du workflow."
                  }
                }
              },
              "example": {
                "ownership_percent": 55
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Brouillon mis à jour.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "draft_id",
                    "created_at",
                    "updated_at",
                    "party"
                  ],
                  "properties": {
                    "draft_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "party": {
                      "type": "object",
                      "required": [
                        "entity_type",
                        "nationality"
                      ],
                      "properties": {
                        "entity_type": {
                          "type": "string",
                          "enum": [
                            "person",
                            "company"
                          ],
                          "description": "Indique si la partie est un particulier ou une entreprise."
                        },
                        "full_name": {
                          "type": "string",
                          "maxLength": 255,
                          "description": "Nom complet d'une personne. Envoyez-le, ou transmettez `first_name` et `last_name`."
                        },
                        "first_name": {
                          "type": "string",
                          "maxLength": 128
                        },
                        "last_name": {
                          "type": "string",
                          "maxLength": 128
                        },
                        "role": {
                          "type": "string",
                          "enum": [
                            "director",
                            "non_executive_director",
                            "secretary",
                            "chairman",
                            "ubo",
                            "shareholder",
                            "representative",
                            "founder",
                            "legal_advisor",
                            "authorized_signatory",
                            "trustee",
                            "beneficiary",
                            "settlor",
                            "protector",
                            "company_officer",
                            "investor",
                            "other"
                          ],
                          "description": "Rôle que détient la partie. Interchangeable avec `roles` ; lorsque les deux sont envoyés, ils sont fusionnés."
                        },
                        "roles": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "director",
                              "non_executive_director",
                              "secretary",
                              "chairman",
                              "ubo",
                              "shareholder",
                              "representative",
                              "founder",
                              "legal_advisor",
                              "authorized_signatory",
                              "trustee",
                              "beneficiary",
                              "settlor",
                              "protector",
                              "company_officer",
                              "investor",
                              "other"
                            ]
                          },
                          "description": "Chaque rôle détenu par la partie. Une personne a besoin d'au moins un rôle (ici ou dans `role`)."
                        },
                        "position": {
                          "type": "string",
                          "maxLength": 128,
                          "description": "Intitulé du poste d'une personne."
                        },
                        "date_of_birth": {
                          "type": "string",
                          "format": "date",
                          "nullable": true
                        },
                        "company_name": {
                          "type": "string",
                          "maxLength": 255,
                          "description": "Nom d'une partie représentant l'entreprise. Requis lorsque `entity_type` est `company`."
                        },
                        "registration_number": {
                          "type": "string",
                          "maxLength": 100,
                          "description": "Numéro d'immatriculation d'une partie de l'entreprise."
                        },
                        "email": {
                          "type": "string",
                          "format": "email",
                          "description": "Destination d'envoi du lien de vérification. Requis lorsque la partie doit effectuer une vérification, ce qui dépend des paramètres de rôle et des seuils d'actionnariat du workflow."
                        },
                        "ownership_percent": {
                          "type": "number",
                          "nullable": true,
                          "description": "Part de l'entreprise détenue par la partie."
                        },
                        "nationality": {
                          "type": "string",
                          "maxLength": 100,
                          "description": "Nationalité d'une personne, ou pays de constitution d'une entreprise. Obligatoire pour chaque partie."
                        },
                        "phone_number": {
                          "type": "string",
                          "maxLength": 32
                        },
                        "custom_fields": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Champs supplémentaires définis par le workflow."
                        },
                        "skip_verification": {
                          "type": "boolean",
                          "default": false,
                          "description": "Demander d'ignorer la vérification de cette partie. Pris en compte uniquement lorsque le rôle de la partie permet de l'ignorer dans les paramètres Personnes clés du workflow."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "draft_id": "5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d",
                  "created_at": "2026-10-31T10:00:00Z",
                  "updated_at": "2026-10-31T10:00:00Z",
                  "party": {
                    "entity_type": "person",
                    "first_name": "Ana",
                    "last_name": "Lopez",
                    "roles": [
                      "ubo",
                      "director"
                    ],
                    "ownership_percent": 55,
                    "nationality": "MEX",
                    "email": "ana.lopez@example.com",
                    "date_of_birth": "1984-06-12"
                  }
                }
              }
            }
          },
          "400": {
            "description": "La partie fusionnée n'est pas valide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "non_field_errors": [
                    "Person parties require at least one role."
                  ]
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session ou le brouillon n'existe pas, ou la session se trouve en dehors de l'application de la clé ou des limites d'une clé restreinte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Session not found."
                }
              }
            }
          },
          "409": {
            "description": "La session est terminée (`kyb_session_not_writable`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "This verification session is no longer accepting changes.",
                  "code": "kyb_session_not_writable"
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 300 requêtes d'écriture (POST, PATCH, DELETE) par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.update_kyb_party_draft(\n    \"33333333-4444-5555-6666-777777777777\",\n    \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\",\n    ownership_percent=55.0,\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.updateKybPartyDraft(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\",\n  {\n    ownership_percent: 55.0,\n  },\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateKYBPartyDraft(ctx, \"33333333-4444-5555-6666-777777777777\", \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\", didit.SessionsUpdateKYBPartyDraftParams{\n\tOwnershipPercent: didit.Float(55.0),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsUpdateKybPartyDraftParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().updateKybPartyDraft(\"33333333-4444-5555-6666-777777777777\", \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\", SessionsUpdateKybPartyDraftParams.builder()\n        .ownershipPercent(55.0)\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->updateKybPartyDraft('33333333-4444-5555-6666-777777777777', '5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d', [\n    'ownership_percent' => 55.0,\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.update_kyb_party_draft(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\",\n  ownership_percent: 55.0\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.UpdateKybPartyDraftAsync(\"33333333-4444-5555-6666-777777777777\", \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\", new SessionsUpdateKybPartyDraftParams\n{\n    OwnershipPercent = 55.0,\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer un brouillon de partie prenante KYB",
        "description": "Supprimer un brouillon de partie. Les parties déclarées ne sont pas affectées. Nécessite `write:businesses`.",
        "operationId": "delete_v3_session_kyb_party_draft",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "delete_kyb_party_draft",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification d'entreprise (KYB). Il doit appartenir à l'application de la clé API.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "draftId",
            "in": "path",
            "required": true,
            "description": "UUID du brouillon de la partie (`draft_id` renvoyé lors de sa création).",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud de workflow de l'étape KYB. Nécessaire uniquement lorsque le workflow comporte plus d'un nœud KYB ; par défaut, Didit utilise le nœud propre à la session.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Brouillon supprimé. Aucun contenu."
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session ou le brouillon n'existe pas, ou la session se trouve en dehors de l'application de la clé ou des limites d'une clé restreinte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Session not found."
                }
              }
            }
          },
          "409": {
            "description": "La session est terminée (`kyb_session_not_writable`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "This verification session is no longer accepting changes.",
                  "code": "kyb_session_not_writable"
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 300 requêtes d'écriture (POST, PATCH, DELETE) par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nclient.sessions.delete_kyb_party_draft(\n    \"33333333-4444-5555-6666-777777777777\",\n    \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\",\n)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nawait didit.sessions.deleteKybPartyDraft(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\",\n);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nif err := client.Sessions.DeleteKYBPartyDraft(ctx, \"33333333-4444-5555-6666-777777777777\", \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\", didit.SessionsDeleteKYBPartyDraftParams{}); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nclient.sessions().deleteKybPartyDraft(\"33333333-4444-5555-6666-777777777777\", \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\");"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$didit->sessions->deleteKybPartyDraft('33333333-4444-5555-6666-777777777777', '5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d');"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.sessions.delete_kyb_party_draft(\n  \"33333333-4444-5555-6666-777777777777\",\n  \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\"\n)"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait client.Sessions.DeleteKybPartyDraftAsync(\"33333333-4444-5555-6666-777777777777\", \"5b0d7a52-9d3e-4f0c-8c6a-0e5f3a1b2c4d\");"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/kyb/parties/submit/": {
      "post": {
        "summary": "Soumettre les brouillons des parties du KYB",
        "description": "Déclarer les brouillons enregistrés comme personnes clés de l'entreprise. Il s'agit de l'étape hébergée Personnes clés sous votre clé API : Didit détermine à partir des paramètres de rôle et des seuils d'actionnariat du workflow quelles parties doivent être vérifiées, crée une session de KYC individuel (ou une sous-session KYB pour un propriétaire personne morale) pour chacune d'elles, envoie les e-mails demandés par le workflow et fait avancer la session. Chaque session enfant est facturée comme dans le flux hébergé. Les brouillons sont consommés. Répéter l'appel après une soumission réussie ne change rien et renvoie `200` avec `already_submitted: true` et les parties qui existent déjà. La session doit se trouver à l'étape Personnes clés. Envoyez l'`kyc_session_url` de chaque personne à celle-ci, ou intégrez-la. Nécessite `write:businesses`.",
        "operationId": "post_v3_session_kyb_parties_submit",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "submit_kyb_parties",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de Vérification d'entreprise (KYB). Il doit appartenir à l'application de la clé API.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "33333333-4444-5555-6666-777777777777"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "description": "Nœud de workflow de l'étape KYB. Nécessaire uniquement lorsque le workflow comporte plus d'un nœud KYB ; par défaut, Didit utilise le nœud propre à la session.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "locale": {
                    "type": "string",
                    "maxLength": 10,
                    "description": "Locale utilisée pour traduire la réponse de l'étape vers laquelle la session avance."
                  }
                }
              },
              "example": {
                "locale": "es"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Parties déclarées (ou déjà déclarées).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean"
                    },
                    "next_step": {
                      "type": "string",
                      "nullable": true,
                      "description": "Étape où se trouve la session."
                    },
                    "status": {
                      "type": "string",
                      "description": "Statut de la session d'entreprise."
                    },
                    "advanced": {
                      "type": "boolean",
                      "description": "`true` lorsque cet appel a déclaré les parties et fait avancer la session."
                    },
                    "already_submitted": {
                      "type": "boolean",
                      "description": "`true` lorsque les parties avaient été déclarées par un appel antérieur."
                    },
                    "kyb_key_people_status": {
                      "type": "string"
                    },
                    "parties": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KYBKeyPeopleParty"
                      }
                    }
                  }
                },
                "example": {
                  "valid": true,
                  "next_step": "FINISHED",
                  "status": "In Progress",
                  "advanced": true,
                  "already_submitted": false,
                  "kyb_key_people_status": "In Progress",
                  "parties": []
                }
              }
            }
          },
          "402": {
            "description": "L'organisation n'a plus de crédit pour les sessions de vérification enfants.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Insufficient credits."
                }
              }
            }
          },
          "401": {
            "description": "La clé API restreinte a expiré. C'est le seul cas qui renvoie `401` : une clé manquante, invalide ou révoquée renvoie `403`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Expired key": {
                    "summary": "La date d'expiration de la clé est dépassée",
                    "value": {
                      "detail": "This API key has expired."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Échec d'authentification ou d'autorisation. Une clé manquante renvoie `403`, tout comme la clé d'une autre application, une clé restreinte ne disposant pas de l'autorisation requise par cet endpoint, ou une requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé ; une clé incorrecte, révoquée ou expirée renvoie `401`. Distinguez-les grâce au champ `detail`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Missing or invalid credentials": {
                    "summary": "Aucun en-tête x-api-key, ou la validation de la clé a échoué",
                    "value": {
                      "detail": "Authentication credentials were not provided or are invalid."
                    }
                  },
                  "Other application": {
                    "summary": "Une clé valide qui appartient à une application différente de la session",
                    "value": {
                      "detail": "You do not have permission to perform this action."
                    }
                  },
                  "Scoped key without decisions write": {
                    "summary": "La clé restreinte ne dispose pas de decisions: write",
                    "value": {
                      "detail": "This API key has no write access to decisions."
                    }
                  },
                  "IP not allowed": {
                    "summary": "Requête provenant de l'extérieur de la liste d'adresses IP autorisées de la clé",
                    "value": {
                      "detail": "This API key can't be used from this IP address."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "La session n'existe pas, a été supprimée, appartient à une autre application ou se trouve en dehors des limites d'une clé restreinte ; aucun détail ne permet de les distinguer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "example": {
                  "detail": "Session not found."
                }
              }
            }
          },
          "409": {
            "description": "`kyb_no_party_drafts` : il n'y a rien à soumettre. `kyb_parties_already_submitted` : des brouillons ont été ajoutés après la déclaration des parties. `kyb_step_mismatch` : la session n'est pas à l'étape Personnes clés (`next_step` indique son étape). `kyb_session_not_writable` : la session est terminée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    },
                    "code": {
                      "type": "string"
                    },
                    "next_step": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "There are no draft parties to submit.",
                  "code": "kyb_no_party_drafts"
                }
              }
            }
          },
          "429": {
            "description": "Limite de débit dépassée : 300 requêtes d'écriture (POST, PATCH, DELETE) par minute par clé API. Attendez `Retry-After` secondes avant de réessayer ; les en-têtes `X-RateLimit-*` indiquent le budget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "description": "Message d'erreur lisible par l'humain."
                    }
                  }
                },
                "examples": {
                  "Rate limited": {
                    "summary": "Budget épuisé pour la minute en cours",
                    "value": {
                      "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Secondes à attendre avant de réessayer.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "example": 30
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.submit_kyb_parties(\n    \"33333333-4444-5555-6666-777777777777\",\n    locale=\"es\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.submitKybParties(\"33333333-4444-5555-6666-777777777777\", {\n  locale: \"es\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.SubmitKYBParties(ctx, \"33333333-4444-5555-6666-777777777777\", didit.SessionsSubmitKYBPartiesParams{\n\tLocale: didit.String(\"es\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.SessionsSubmitKybPartiesParams;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().submitKybParties(\"33333333-4444-5555-6666-777777777777\", SessionsSubmitKybPartiesParams.builder()\n        .locale(\"es\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->submitKybParties('33333333-4444-5555-6666-777777777777', [\n    'locale' => 'es',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.submit_kyb_parties(\n  \"33333333-4444-5555-6666-777777777777\",\n  locale: \"es\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.SubmitKybPartiesAsync(\"33333333-4444-5555-6666-777777777777\", new SessionsSubmitKybPartiesParams\n{\n    Locale = \"es\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    },
    "/v3/session/{sessionId}/files-export/": {
      "post": {
        "summary": "Exporter tous les fichiers d'une session",
        "description": "Démarrer la préparation d'un fichier ZIP contenant chaque image, vidéo et document d'une session de Vérification des utilisateurs (KYC) ou de Vérification d'entreprise (KYB), en qualité originale : les fichiers sont stockés dans le ZIP tels qu'ils ont été capturés, sans jamais être recompressés. Répond `202` avec l'export ; lisez-le avec `GET /v3/session/{sessionId}/files-export/{exportId}/` jusqu'à ce que `status` soit `READY`, puis téléchargez `download_url`. Tant qu'un export de la même session est toujours en cours de préparation, cet export est renvoyé au lieu d'en créer un nouveau.\n\nLe ZIP est supprimé 24 heures après qu'il est prêt, et immédiatement lorsque la session est supprimée. Une session supprimée ne peut pas être exportée. Chaque export et chaque lien de téléchargement délivré est consigné dans le journal d'audit de la session. Une clé API restreinte nécessite `media: read` et `decisions: read` ; un utilisateur de la console a besoin de l'autorisation de lire les sessions.",
        "operationId": "post_v3_session_files_export",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "export_files",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification (le `session_id` renvoyé par `POST /v3/session/`). Accepte les identifiants de session de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB). Une session supprimée renvoie `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X POST 'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/files-export/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.export_files(\n    \"11111111-2222-3333-4444-555555555555\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.exportFiles(\"11111111-2222-3333-4444-555555555555\");\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.ExportFiles(ctx, \"11111111-2222-3333-4444-555555555555\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().exportFiles(\"11111111-2222-3333-4444-555555555555\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->exportFiles('11111111-2222-3333-4444-555555555555');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.export_files(\"11111111-2222-3333-4444-555555555555\")\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.ExportFilesAsync(\"11111111-2222-3333-4444-555555555555\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "202": {
            "description": "L'export, en cours de préparation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionFilesExport"
                },
                "example": {
                  "export_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                  "session_id": "11111111-2222-3333-4444-555555555555",
                  "status": "PENDING",
                  "file_count": null,
                  "size_bytes": null,
                  "download_url": null,
                  "expires_at": null,
                  "error": null,
                  "created_at": "2026-10-29T12:00:03Z",
                  "completed_at": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/session/{sessionId}/files-export/{exportId}/": {
      "get": {
        "summary": "Obtenir un export de fichiers de session",
        "description": "Progression d'un export démarré avec `POST /v3/session/{sessionId}/files-export/`. Dès que `status` est `READY`, `download_url` est une URL signée du fichier ZIP qui reste valide pendant une courte durée ; relisez l'export pour en obtenir une nouvelle jusqu'à `expires_at`. Chaque lecture délivrant un lien de téléchargement est inscrite dans le journal d'audit de la session. L'export d'une session supprimée renvoie `404`.",
        "operationId": "get_v3_session_files_export",
        "x-didit-sdk": {
          "resource": "sessions",
          "method": "get_files_export",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Sessions"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "UUID de la session de vérification (le `session_id` renvoyé par `POST /v3/session/`). Accepte les identifiants de session de Vérification des utilisateurs (KYC) et de Vérification d'entreprise (KYB). Une session supprimée renvoie `404`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "11111111-2222-3333-4444-555555555555"
            }
          },
          {
            "name": "exportId",
            "in": "path",
            "required": true,
            "description": "L'`export_id` renvoyé par `POST /v3/session/{sessionId}/files-export/`.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl -X GET 'https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/files-export/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.sessions.get_files_export(\n    \"11111111-2222-3333-4444-555555555555\",\n    \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.sessions.getFilesExport(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\n);\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.GetFilesExport(ctx, \"11111111-2222-3333-4444-555555555555\", \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\")\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.sessions().getFilesExport(\"11111111-2222-3333-4444-555555555555\", \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\");\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->sessions->getFilesExport('11111111-2222-3333-4444-555555555555', 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee');\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.sessions.get_files_export(\n  \"11111111-2222-3333-4444-555555555555\",\n  \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.Sessions.GetFilesExportAsync(\"11111111-2222-3333-4444-555555555555\", \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\");\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ],
        "responses": {
          "200": {
            "description": "L'export.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionFilesExport"
                },
                "example": {
                  "export_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                  "session_id": "11111111-2222-3333-4444-555555555555",
                  "status": "READY",
                  "file_count": 9,
                  "size_bytes": 18734120,
                  "download_url": "https://storage.example.com/session/11111111-2222-3333-4444-555555555555/files-export/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/session-42-files.zip?X-Amz-Signature=...",
                  "expires_at": "2026-10-30T12:00:41Z",
                  "error": null,
                  "created_at": "2026-10-29T12:00:03Z",
                  "completed_at": "2026-10-29T12:00:41Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/travel-rule/unmatched/": {
      "get": {
        "summary": "Lister les dépôts Travel Rule sans correspondance",
        "description": "Dépôts entrants toujours en attente des données Travel Rule du VASP d'origine : leur transfert est à l'état `AWAITING_COUNTERPARTY`, `NOT_ENOUGH_COUNTERPARTY_DATA` ou `COUNTERPARTY_VASP_NOT_FOUND`, aucun message reçu ne leur est associé, et personne ne les a mis en correspondance manuellement. Les lignes et les filtres sont les mêmes que dans `GET /v3/travel-rule/transfers/`, les plus récents en premier, paginés avec `limit` (50 par défaut) et `offset`. Associez un dépôt au message envoyé par le VASP d'origine avec `POST /v3/travel-rule/unmatched/{transaction_uuid}/match/`.",
        "operationId": "listUnmatchedTravelRuleDeposits",
        "x-didit-sdk": {
          "resource": "travel_rule.unmatched_deposits",
          "method": "list",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "INBOUND, OUTBOUND, ou les deux séparés par une virgule. Sensible à la casse."
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Un ou plusieurs statuts de transfert, séparés par des virgules."
          },
          {
            "name": "rail",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Un ou plusieurs parmi INTERNAL, TRP, GTR, TRUST, VERIFYVASP, SYGNA, EMAIL, TEST_VASP, séparés par des virgules."
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "withdrawal, deposit ou message, séparés par des virgules."
          },
          {
            "name": "currency",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "La devise de la transaction, insensible à la casse."
          },
          {
            "name": "start_date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Transferts créés à cette date ou après (UTC), YYYY-MM-DD."
          },
          {
            "name": "end_date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Transferts créés à cette date ou avant (UTC), YYYY-MM-DD."
          },
          {
            "name": "counterparty",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "L'`id` d'une entrée d'annuaire ou d'un membre du réseau Didit provenant de GET /v3/travel-rule/vasps/ : vos transferts avec cette contrepartie. Une valeur qui n'est pas un identifiant valide renvoie une réponse 400."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000000
            },
            "description": "Taille de page, 50 par défaut."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000000
            },
            "description": "Lignes à ignorer."
          }
        ],
        "responses": {
          "200": {
            "description": "Une page de dépôts non appariés.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous": {
                      "type": "string",
                      "nullable": true
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TravelRuleTransferRow"
                      }
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next": null,
                  "previous": null,
                  "results": [
                    {
                      "id": "7d3a1c55-0b9e-4d52-8a3c-1f6e2b9d4a08",
                      "transaction_id": "c41f9b2e-5a8d-4e0c-9f17-3b6d8a2e5c91",
                      "txn_id": "dep-2026-10-20-0007",
                      "txn_date": "2026-10-19T08:41:12Z",
                      "kind": "deposit",
                      "direction": "INBOUND",
                      "status": "AWAITING_COUNTERPARTY",
                      "rail": "TRP",
                      "asset": "ETH",
                      "amount": "1.25",
                      "originator_vasp": "",
                      "beneficiary_vasp": "Example Counterparty VASP",
                      "originator_wallet": "0x77ccff0cc624a53cd8b8d8703ced826710211ec7",
                      "beneficiary_wallet": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
                      "originator_memo": "",
                      "beneficiary_memo": "",
                      "originator_wallet_type": "vasp",
                      "beneficiary_wallet_type": "vasp",
                      "matched_transaction_id": null,
                      "deadline_at": null,
                      "created_at": "2026-10-19T08:41:13Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Une valeur de filtre n'est pas valide.",
            "content": {
              "application/json": {
                "example": {
                  "start_date": [
                    "Use the YYYY-MM-DD format."
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nfor item in client.travel_rule.unmatched_deposits.list():\n    print(item)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nfor await (const item of didit.travelRule.unmatchedDeposits.list()) {\n  console.log(item);\n}"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\niter := client.TravelRule.UnmatchedDeposits.ListAutoPaging(ctx, didit.TravelRuleUnmatchedDepositsListParams{})\nfor iter.Next() {\n\tfmt.Printf(\"%+v\\n\", iter.Current())\n}\nif err := iter.Err(); err != nil {\n\tlog.Fatal(err)\n}"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nfor (var item : client.travelRule().unmatchedDeposits().list()) {\n    System.out.println(item);\n}"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\nforeach ($didit->travelRule->unmatchedDeposits->list() as $item) {\n    print_r($item->toArray());\n}"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\ndidit.travel_rule.unmatched_deposits.list.auto_paging_each do |item|\n  puts item.to_h\nend"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nawait foreach (var item in await client.TravelRule.UnmatchedDeposits.ListAsync())\n{\n    Console.WriteLine(JsonSerializer.Serialize(item));\n}"
          }
        ]
      }
    },
    "/v3/travel-rule/unmatched/{transaction_uuid}/match/": {
      "post": {
        "summary": "Faire correspondre un dépôt Travel Rule à un message reçu",
        "operationId": "matchUnmatchedTravelRuleDeposit",
        "x-didit-sdk": {
          "resource": "travel_rule.unmatched_deposits",
          "method": "match",
          "auth": "api_key",
          "server": true
        },
        "tags": [
          "Travel Rule"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Associez un dépôt entrant toujours en attente des données du donneur d'ordre au message Travel Rule que le VASP donneur d'ordre a envoyé pour celui-ci. Le dépôt prend les données de donneur d'ordre, le VASP de contrepartie et le rail du message, et les deux transferts enregistrent la correspondance sur leur chronologie. `transaction_uuid` correspond au `transaction_id` du dépôt obtenu via `GET /v3/travel-rule/unmatched/`. Le champ `transaction_id` dans le corps de la requête est le `transaction_id` du message reçu, provenant d'une ligne de `GET /v3/travel-rule/transfers/?kind=message` ; l'`id` propre du transfert n'est pas trouvé. Le message doit concerner le même actif que le dépôt. Un dépôt ou un message supprimé depuis la Console renvoie `404` ; un élément déjà traité (associé ou qui n'est plus en attente) renvoie `409`.",
        "parameters": [
          {
            "name": "transaction_uuid",
            "in": "path",
            "required": true,
            "description": "Le `transaction_id` du dépôt non rapproché.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleManualMatchRequest"
              },
              "example": {
                "transaction_id": "e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Les deux transferts après la correspondance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TravelRuleManualMatchResponse"
                },
                "example": {
                  "deposit": {
                    "id": "7d3a1c55-0b9e-4d52-8a3c-1f6e2b9d4a08",
                    "transaction_id": "c41f9b2e-5a8d-4e0c-9f17-3b6d8a2e5c91",
                    "txn_id": "dep-2026-10-20-0007",
                    "txn_date": "2026-10-19T08:41:12Z",
                    "kind": "deposit",
                    "direction": "INBOUND",
                    "status": "AWAITING_COUNTERPARTY",
                    "rail": "TRP",
                    "asset": "ETH",
                    "amount": "1.25",
                    "originator_vasp": "Example Counterparty VASP",
                    "beneficiary_vasp": "Example Counterparty VASP",
                    "originator_wallet": "0x77ccff0cc624a53cd8b8d8703ced826710211ec7",
                    "beneficiary_wallet": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
                    "originator_memo": "",
                    "beneficiary_memo": "",
                    "originator_wallet_type": "vasp",
                    "beneficiary_wallet_type": "vasp",
                    "matched_transaction_id": "e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24",
                    "deadline_at": null,
                    "created_at": "2026-10-19T08:41:13Z"
                  },
                  "message": {
                    "id": "2b8e6f10-9c3a-47d1-b5e2-0a4c7d9f3e66",
                    "transaction_id": "e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24",
                    "txn_id": "msg-2026-10-20-0003",
                    "txn_date": "2026-10-19T08:41:12Z",
                    "kind": "message",
                    "direction": "INBOUND",
                    "status": "COMPLETED",
                    "rail": "TRP",
                    "asset": "ETH",
                    "amount": "1.25",
                    "originator_vasp": "Origin CASP SL",
                    "beneficiary_vasp": "Example Counterparty VASP",
                    "originator_wallet": "0x77ccff0cc624a53cd8b8d8703ced826710211ec7",
                    "beneficiary_wallet": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
                    "originator_memo": "",
                    "beneficiary_memo": "",
                    "originator_wallet_type": "vasp",
                    "beneficiary_wallet_type": "vasp",
                    "matched_transaction_id": null,
                    "deadline_at": "2026-10-21T08:41:13Z",
                    "created_at": "2026-10-19T08:41:13Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation : `transaction_id` est manquant, correspond au dépôt lui-même, n'est pas un message Travel Rule reçu, ou concerne un actif différent de celui du dépôt ; ou la transaction indiquée dans le chemin n'est pas un dépôt entrant.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Error": {
                    "value": {
                      "transaction_id": [
                        "The travel rule message is for a different asset than the deposit."
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Dépôt ou message inconnu, ou l'un d'eux a été supprimé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "detail": "No TravelRuleTransfer matches the given query."
                }
              }
            }
          },
          "409": {
            "description": "Le dépôt n'est plus en attente des données du donneur d'ordre, ou le message est déjà associé à un dépôt.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Error": {
                    "value": {
                      "detail": "This deposit is no longer waiting for originator data."
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "python",
            "label": "Python",
            "source": "from didit import Didit\n\n# Reads DIDIT_API_KEY.\nclient = Didit()\n\nresult = client.travel_rule.unmatched_deposits.match(\n    \"11111111-2222-3333-4444-555555555555\",\n    transaction_id=\"e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24\",\n)\nprint(result)"
          },
          {
            "lang": "javascript",
            "label": "Node.js",
            "source": "import Didit from \"@didit-protocol/sdk-node\";\n\n// Reads DIDIT_API_KEY.\nconst didit = new Didit();\n\nconst result = await didit.travelRule.unmatchedDeposits.match(\"11111111-2222-3333-4444-555555555555\", {\n  transaction_id: \"e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24\",\n});\nconsole.log(result);"
          },
          {
            "lang": "go",
            "label": "Go",
            "source": "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.TravelRule.UnmatchedDeposits.Match(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleManualMatchRequest{\n\tTransactionID: \"e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
          },
          {
            "lang": "java",
            "label": "Java",
            "source": "import me.didit.Didit;\nimport me.didit.types.TravelRuleManualMatchRequest;\n\n// Reads DIDIT_API_KEY.\nDidit client = new Didit();\n\nvar result = client.travelRule().unmatchedDeposits().match(\"11111111-2222-3333-4444-555555555555\", TravelRuleManualMatchRequest.builder()\n        .transactionId(\"e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24\")\n        .build());\nSystem.out.println(result);"
          },
          {
            "lang": "php",
            "label": "PHP",
            "source": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Didit\\DiditClient;\n\n// Reads DIDIT_API_KEY.\n$didit = new DiditClient();\n\n$result = $didit->travelRule->unmatchedDeposits->match('11111111-2222-3333-4444-555555555555', [\n    'transaction_id' => 'e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24',\n]);\nprint_r($result->toArray());"
          },
          {
            "lang": "ruby",
            "label": "Ruby",
            "source": "require \"didit\"\n\n# Reads DIDIT_API_KEY.\ndidit = Didit::Client.new\n\nresult = didit.travel_rule.unmatched_deposits.match(\n  \"11111111-2222-3333-4444-555555555555\",\n  transaction_id: \"e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24\"\n)\nputs result.to_h"
          },
          {
            "lang": "csharp",
            "label": ".NET",
            "source": "using System;\nusing System.Text.Json;\nusing Didit;\n\n// Reads DIDIT_API_KEY.\nusing var client = new DiditClient();\n\nvar result = await client.TravelRule.UnmatchedDeposits.MatchAsync(\"11111111-2222-3333-4444-555555555555\", new TravelRuleManualMatchRequest\n{\n    TransactionId = \"e90a4d7b-1c2f-4b83-a6d5-8f0e3c1b7a24\",\n});\nConsole.WriteLine(JsonSerializer.Serialize(result));"
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "DocumentAIDetectedCode": {
        "type": "object",
        "required": [
          "type",
          "page_number",
          "position",
          "x",
          "y",
          "width",
          "height",
          "page_width",
          "page_height",
          "raw_payload",
          "parsed_payload"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Symbologie détectée, par exemple `QR_CODE`, `CODE_128`, `EAN_13`, `DATA_MATRIX` ou `PDF_417`."
          },
          "page_number": {
            "type": "integer",
            "minimum": 1,
            "description": "Numéro de page (à partir de 1)."
          },
          "position": {
            "type": "array",
            "nullable": true,
            "description": "Polygone détecté en coordonnées de pixels de la page rendue. `null` lorsqu'aucun emplacement fiable n'est disponible.",
            "items": {
              "type": "array",
              "minItems": 2,
              "maxItems": 2,
              "items": {
                "type": "integer"
              }
            }
          },
          "x": {
            "type": "integer",
            "nullable": true,
            "description": "Bord gauche de la boîte englobante en pixels de la page rendue."
          },
          "y": {
            "type": "integer",
            "nullable": true,
            "description": "Bord supérieur de la boîte englobante en pixels de la page rendue."
          },
          "width": {
            "type": "integer",
            "nullable": true,
            "description": "Largeur de la boîte englobante en pixels de la page rendue."
          },
          "height": {
            "type": "integer",
            "nullable": true,
            "description": "Hauteur de la boîte englobante en pixels de la page rendue."
          },
          "page_width": {
            "type": "integer",
            "description": "Largeur de la page générée en pixels."
          },
          "page_height": {
            "type": "integer",
            "description": "Hauteur de la page générée en pixels."
          },
          "raw_payload": {
            "type": "string",
            "description": "Payload brut du décodeur sous forme de chaîne base64 lorsqu'il est disponible ; sinon chaîne vide."
          },
          "parsed_payload": {
            "nullable": true,
            "description": "Chaîne décodée ou valeur structurée. `null` lorsque le code a été localisé mais n'a pas pu être décodé."
          }
        }
      },
      "SessionImportJob": {
        "type": "object",
        "required": [
          "uuid",
          "status",
          "import_type",
          "source_format",
          "source_filename",
          "total_rows",
          "processed_rows",
          "created_count",
          "updated_count",
          "skipped_count",
          "failed_count"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de la tâche d'importation. Utilisez cette valeur pour suivre la progression et récupérer les erreurs de ligne."
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "COMPLETED",
              "FAILED",
              "PAUSED",
              "CANCELLED",
              "READY"
            ]
          },
          "import_type": {
            "type": "string",
            "enum": [
              "user_verification",
              "business_verification",
              "status_rules",
              "transactions"
            ]
          },
          "source_format": {
            "type": "string",
            "enum": [
              "csv",
              "ndjson"
            ]
          },
          "source_filename": {
            "type": "string"
          },
          "total_rows": {
            "type": "integer",
            "format": "int64"
          },
          "processed_rows": {
            "type": "integer",
            "format": "int64"
          },
          "checkpoint_row": {
            "type": "integer",
            "format": "int64"
          },
          "created_count": {
            "type": "integer",
            "format": "int64"
          },
          "updated_count": {
            "type": "integer",
            "format": "int64"
          },
          "skipped_count": {
            "type": "integer",
            "format": "int64"
          },
          "failed_count": {
            "type": "integer",
            "format": "int64"
          },
          "total_media_bytes": {
            "type": "integer",
            "format": "int64"
          },
          "last_error": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "state": {
            "type": "string",
            "enum": [
              "ready",
              "queued",
              "running",
              "paused",
              "completed",
              "errors",
              "failed",
              "cancelled"
            ],
            "description": "L'état de la tâche tel qu'affiché dans la console ; `errors` correspond à une tâche terminée avec des lignes rejetées."
          },
          "source": {
            "type": "string",
            "enum": [
              "file",
              "api",
              "provider"
            ]
          },
          "provider": {
            "type": "string",
            "description": "Source de migration ; vide pour une importation par fichier ou par API."
          },
          "provider_options": {
            "type": "object"
          },
          "credential_hint": {
            "type": "string",
            "description": "Les premiers caractères de la clé détenue par la migration. La clé elle-même n'est jamais renvoyée."
          },
          "credentials_expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resumes_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où une tâche mise en pause par la limite de débit du fournisseur reprend d'elle-même."
          },
          "status_mapping": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "is_dry_run": {
            "type": "boolean"
          },
          "dry_run_summary": {
            "type": "object",
            "description": "Ce qu'une exécution à blanc a trouvé : `total`, `by_status`, `already_in_didit`, `same_person`, `not_finished`, `failed`, `unmapped_statuses`."
          },
          "face_templates_enabled": {
            "type": "boolean"
          },
          "lawful_basis_confirmed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "not_finished_count": {
            "type": "integer",
            "format": "int64"
          },
          "same_person_count": {
            "type": "integer",
            "format": "int64"
          },
          "face_templates_count": {
            "type": "integer",
            "format": "int64"
          },
          "face_duplicates_count": {
            "type": "integer",
            "format": "int64"
          },
          "face_blocklist_hits_count": {
            "type": "integer",
            "format": "int64"
          },
          "created_by_name": {
            "type": "string",
            "nullable": true
          },
          "created_by_email": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "SessionImportError": {
        "type": "object",
        "required": [
          "uuid",
          "row_number",
          "error",
          "raw_row"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "row_number": {
            "type": "integer",
            "format": "int64"
          },
          "external_id": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string"
          },
          "raw_row": {
            "type": "object",
            "additionalProperties": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BrandingCustomizationUpdate": {
        "type": "object",
        "description": "Corps de mise à jour partielle de la marque. Ne fournissez que les champs que vous souhaitez modifier. Les couleurs hexadécimales acceptent `#RRGGBB` ou `#RRGGBBAA`. Le domaine personnalisé et l'e-mail en marque blanche ne sont pas acceptés ici.",
        "properties": {
          "color_primary": {
            "type": "string",
            "description": "Couleur des en-têtes / du texte principal."
          },
          "color_secondary": {
            "type": "string",
            "description": "Couleur de paragraphe / texte secondaire."
          },
          "color_background": {
            "type": "string",
            "description": "Couleur d'arrière-plan de la page."
          },
          "color_panel": {
            "type": "string",
            "description": "Couleur de panneau / d'accentuation."
          },
          "color_panel_10": {
            "type": "string",
            "description": "Couleur de panneau à 10 % d'opacité."
          },
          "color_on_panel_1": {
            "type": "string",
            "description": "Couleur du texte d'assistance sur les panneaux."
          },
          "color_on_panel_2": {
            "type": "string",
            "description": "Couleur de la pastille / du badge sur les panneaux."
          },
          "color_on_background": {
            "type": "string",
            "description": "Couleur du texte sur l'arrière-plan."
          },
          "color_button_1": {
            "type": "string",
            "description": "Couleur du bouton principal."
          },
          "color_button_2": {
            "type": "string",
            "description": "Couleur du bouton secondaire."
          },
          "color_button_text_1": {
            "type": "string",
            "description": "Couleur du texte du bouton principal."
          },
          "color_button_text_2": {
            "type": "string",
            "description": "Couleur du texte du bouton secondaire."
          },
          "color_pill_text": {
            "type": "string",
            "description": "Couleur du texte pour les badges, champs de saisie et sélecteurs."
          },
          "border_radius_panel": {
            "type": "integer",
            "minimum": 0,
            "description": "Rayon des angles du panneau en pixels."
          },
          "border_radius_buttons": {
            "type": "integer",
            "minimum": 0,
            "description": "Rayon d'arrondi des coins du bouton en pixels."
          },
          "font_family": {
            "type": "string",
            "description": "Nom de la famille de polices Google (par exemple `Inter`, `AR One Sans`)."
          },
          "font_weight": {
            "type": "string",
            "description": "Graisse de police disponible pour la famille sélectionnée (par ex. `regular`, `500`, `700`)."
          },
          "app_public_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom public affiché dans le flux de vérification."
          },
          "privacy_policy_url": {
            "type": "string",
            "nullable": true,
            "description": "URL de la politique de confidentialité affichée à l'utilisateur final."
          },
          "skip_welcome_screen": {
            "type": "boolean",
            "description": "Ignorer l'écran de bienvenue initial."
          },
          "disable_login_with_didit": {
            "type": "boolean",
            "description": "Continuer en tant qu'invité au lieu d'afficher l'écran de connexion avec Didit. Ne peut pas être remis à `false` tant qu'un domaine personnalisé est configuré (400)."
          },
          "hide_progress_bar": {
            "type": "boolean",
            "description": "Masquer la barre de progression pendant le flux."
          },
          "callback_seconds": {
            "type": "integer",
            "minimum": 0,
            "description": "Délai (secondes) avant la redirection vers l'URL de rappel."
          },
          "delete_logo_square": {
            "type": "boolean",
            "description": "Lorsque la valeur est `true`, supprime le logo carré actuel."
          },
          "delete_logo_rectangular": {
            "type": "boolean",
            "description": "Lorsque la valeur est `true`, supprime le logo rectangulaire actuel."
          },
          "delete_logo_rectangular_dark": {
            "type": "boolean",
            "description": "Lorsque la valeur est `true`, supprime le logo actuel en mode sombre, et `logo_rectangular_dark` renvoie alors `null`. Si la même requête multipart téléverse également `image_rectangular_dark`, le téléversement prévaut."
          },
          "delete_favicon": {
            "type": "boolean",
            "description": "Lorsque la valeur est `true`, supprime le favicon actuel."
          }
        }
      },
      "BrandingCustomization": {
        "type": "object",
        "description": "Personnalisation en marque blanche pour une application : couleurs, polices, arrondis, URL des logos et options UI/UX. Les URL des logos sont en lecture seule (définissez-les en téléversant des images). Le domaine personnalisé et l'e-mail en marque blanche ne sont pas inclus.",
        "properties": {
          "color_primary": {
            "type": "string"
          },
          "color_secondary": {
            "type": "string"
          },
          "color_background": {
            "type": "string"
          },
          "color_panel": {
            "type": "string"
          },
          "color_panel_10": {
            "type": "string"
          },
          "color_on_panel_1": {
            "type": "string"
          },
          "color_on_panel_2": {
            "type": "string"
          },
          "color_on_background": {
            "type": "string"
          },
          "color_button_1": {
            "type": "string"
          },
          "color_button_2": {
            "type": "string"
          },
          "color_button_text_1": {
            "type": "string"
          },
          "color_button_text_2": {
            "type": "string"
          },
          "color_pill_text": {
            "type": "string"
          },
          "border_radius_panel": {
            "type": "integer"
          },
          "border_radius_buttons": {
            "type": "integer"
          },
          "font_family": {
            "type": "string"
          },
          "font_weight": {
            "type": "string"
          },
          "font_url": {
            "type": "string",
            "nullable": true,
            "description": "Lecture seule. URL résolue de la feuille de style Google Fonts pour la famille sélectionnée."
          },
          "logo_square": {
            "type": "string",
            "nullable": true,
            "description": "URL en lecture seule du logo carré. Téléversez via `image_square`."
          },
          "logo_rectangular": {
            "type": "string",
            "nullable": true,
            "description": "URL en lecture seule du logo rectangulaire. Téléversez via `image_rectangular`."
          },
          "logo_rectangular_dark": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Lecture seule. URL signée temporaire du logo rectangulaire pour le mode sombre, affiché sur fond sombre. Vaut `null` lorsqu'aucun logo sombre n'est configuré ou que les logos rectangulaires ne sont pas affichés pour votre compte. Téléversez-le avec `image_rectangular_dark`."
          },
          "favicon": {
            "type": "string",
            "nullable": true,
            "description": "URL en lecture seule du favicon. Téléversez via `image_favicon`."
          },
          "app_public_name": {
            "type": "string",
            "nullable": true
          },
          "privacy_policy_url": {
            "type": "string",
            "nullable": true
          },
          "skip_welcome_screen": {
            "type": "boolean"
          },
          "disable_login_with_didit": {
            "type": "boolean"
          },
          "hide_progress_bar": {
            "type": "boolean"
          },
          "callback_seconds": {
            "type": "integer"
          }
        }
      },
      "WebhookEvent": {
        "type": "string",
        "description": "Nom d'événement webhook pris en charge. Utilisez ces chaînes exactes dans `subscribed_events` ; les valeurs non prises en charge sont rejetées.",
        "enum": [
          "status.updated",
          "data.updated",
          "user.status.updated",
          "user.data.updated",
          "business.status.updated",
          "business.data.updated",
          "activity.created",
          "transaction.created",
          "transaction.status.updated",
          "travel_rule.status.updated",
          "workflow.compliance_changed",
          "transaction_rule_suggestions.created",
          "auth.signup",
          "auth.login",
          "auth.login_failed",
          "auth.password_reset_requested",
          "auth.password_reset_completed",
          "auth.mfa_changed",
          "auth.new_device",
          "auth.account_locked",
          "investigator.report.ready",
          "investigator.decision.automated",
          "investigator.decision.overridden",
          "investigator.decision.contested",
          "investigator.question.raised",
          "investigator.automation.paused",
          "investigator.rfi.answered",
          "investigator.rfi.overdue",
          "investigator.drift.detected",
          "investigator.sla.breached",
          "investigator.qa.failed",
          "investigator.external.report.ready"
        ]
      },
      "WebhookSubscribedEvents": {
        "type": "array",
        "description": "Filtre d'événements pour cette destination de webhook. Didit ne livre que les webhooks dont le type d'événement correspond exactement à l'une de ces valeurs — il n'y a pas d'abonnement avec caractère générique. Lorsqu'elle est envoyée, la liste doit contenir au moins un événement valide (un `[]` explicite est rejeté avec une erreur 400) ; une destination dont la liste est vide (champ omis lors de la création) ne reçoit rien. Lors d'une mise à jour, la liste est entièrement remplacée, jamais fusionnée.",
        "minItems": 1,
        "uniqueItems": true,
        "items": {
          "$ref": "#/components/schemas/WebhookEvent"
        },
        "example": [
          "status.updated",
          "data.updated"
        ]
      },
      "PhoneVerificationSendResponse": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de session de la vérification. Un envoi `Retry` renvoie le même `request_id` que l'envoi initial. Cet identifiant apparaît dans la Business Console, est renvoyé à nouveau par un `POST /v3/phone/check/` finalisé, et peut être transmis à `GET /v3/session/{sessionId}/decision/`."
          },
          "status": {
            "type": "string",
            "enum": [
              "Success",
              "Retry",
              "Blocked"
            ],
            "description": "`Success` — OTP envoyé pour une nouvelle vérification. `Retry` — OTP renvoyé pour la vérification en attente créée par un envoi précédent. `Blocked` — la couche antifraude a refusé l'envoi ; la vérification est immédiatement finalisée comme `Declined` et rien n'est facturé."
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "description": "Raison pour laquelle un envoi a été `Blocked` (par exemple `repeated_attempts`, `suspicious`, `spam`). `null` pour `Success` et `Retry`."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Écho des `vendor_data` stockées sur la session (depuis le premier envoi)."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "description": "Écho des `metadata` stockées sur la session (depuis le premier envoi)."
          }
        }
      },
      "PhoneVerificationCheckResponse": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Pour `Approved`/`Declined` : l'identifiant de session de la vérification correspondante — identique au `request_id` renvoyé par `POST /v3/phone/send/`. Pour `Failed` et `Expired or Not Found` : un UUID aléatoire à usage unique qui ne pourra pas être consulté ultérieurement."
          },
          "status": {
            "type": "string",
            "enum": [
              "Approved",
              "Declined",
              "Failed",
              "Expired or Not Found"
            ],
            "description": "`Approved` — code correct, aucun risque de refus. `Declined` — définitif : un risque entraînant un refus a correspondu ou le nombre maximal de tentatives (3) a été épuisé. `Failed` — code erroné, tentatives restantes. `Expired or Not Found` — aucune vérification en attente pour ce numéro au cours des 5 dernières minutes."
          },
          "message": {
            "type": "string",
            "description": "Explication lisible par l'humain du résultat, incluant le nombre de tentatives restantes après un code erroné."
          },
          "phone": {
            "type": "object",
            "nullable": true,
            "description": "Rapport téléphonique complet. Présent (non nul) uniquement pour les résultats finalisés (`Approved`/`Declined`) ; `null` en cas de `Failed` et absent en cas de `Expired or Not Found`.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "Approved",
                  "Declined",
                  "In Review",
                  "Not Finished",
                  "Expired"
                ],
                "description": "Statut final de la vérification du téléphone. Correspond au `status` de premier niveau pour les vérifications finalisées."
              },
              "phone_number_prefix": {
                "type": "string",
                "description": "Indicatif téléphonique du pays avec un `+` au début (par ex., `+1`).",
                "example": "+1"
              },
              "phone_number": {
                "type": "string",
                "description": "Numéro national sans l'indicatif téléphonique du pays.",
                "example": "4155552671"
              },
              "full_number": {
                "type": "string",
                "description": "Numéro complet au format E.164.",
                "example": "+14155552671"
              },
              "country_code": {
                "type": "string",
                "nullable": true,
                "description": "Pays ISO 3166-1 alpha-2 du numéro.",
                "example": "US"
              },
              "country_name": {
                "type": "string",
                "description": "Nom complet du pays dérivé de `country_code`.",
                "example": "United States"
              },
              "carrier": {
                "type": "object",
                "description": "Réseau actuel desservant le numéro, issu de la recherche d'opérateur effectuée lors de la finalisation.",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nom de l'opérateur. Chaîne vide lorsque la recherche n'a pas pu l'identifier."
                  },
                  "type": {
                    "type": "string",
                    "description": "Type de ligne signalé par la recherche : `mobile`, `fixed_line`, `voip`, `isp`, `vpn`, `toll_free`, `premium_rate`, `pager`, `payphone`, `satellite`, `service`, `shared_cost`, `short_codes_commercial`, `calling_cards`, `local_rate`, `universal_access`, `voice_mail`, `other` ou `unknown`."
                  }
                }
              },
              "is_disposable": {
                "type": "boolean",
                "description": "`true` lorsque le numéro appartient à un service de numéros temporaires/jetables."
              },
              "is_virtual": {
                "type": "boolean",
                "description": "`true` lorsque le type de ligne est virtuel (`voip`, `isp` ou `vpn`)."
              },
              "verification_method": {
                "type": "string",
                "description": "Canal ayant réellement délivré l'OTP une fois la livraison confirmée (par ex. `whatsapp`, `sms`) ; jusqu'à cette confirmation, il s'agit du canal demandé."
              },
              "verification_attempts": {
                "type": "integer",
                "description": "Nombre d'envois d'OTP pour cette vérification (1, ou 2 après une nouvelle tentative)."
              },
              "verified_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure de saisie du code correct. `null` si la vérification n'a jamais été approuvée."
              },
              "warnings": {
                "type": "array",
                "description": "Avertissements de risque enregistrés pendant la vérification (doublon, jetable, VoIP, nombre maximal de tentatives dépassé, liste de blocage, etc.). Tableau vide lorsqu'il n'y en a aucun.",
                "items": {
                  "type": "object",
                  "properties": {
                    "feature": {
                      "type": "string",
                      "description": "Fonctionnalité ayant généré l'avertissement. Toujours `PHONE` ici."
                    },
                    "risk": {
                      "type": "string",
                      "description": "Code de risque lisible par machine."
                    },
                    "additional_data": {
                      "type": "object",
                      "nullable": true,
                      "description": "Contexte spécifique au risque (par ex., l'identifiant de la session dupliquée pour les risques de doublon). `null` lorsque le risque ne comporte aucune donnée supplémentaire."
                    },
                    "log_type": {
                      "type": "string",
                      "enum": [
                        "error",
                        "warning",
                        "information"
                      ],
                      "description": "Gravité. Les risques `error` entraînent le refus de la vérification, `warning` la signale pour examen, et `information` est enregistrée sans affecter le statut."
                    },
                    "short_description": {
                      "type": "string",
                      "description": "Résumé du risque en une ligne, lisible par l'utilisateur."
                    },
                    "long_description": {
                      "type": "string",
                      "description": "Explication lisible par l'humain du risque."
                    }
                  }
                }
              },
              "lifecycle": {
                "type": "array",
                "description": "Piste d'audit chronologique de la vérification. L'événement `type` est l'un des suivants : `PHONE_VERIFICATION_MESSAGE_SENT`, `PHONE_VERIFICATION_RETRY_MESSAGE_SENT`, `PHONE_VERIFICATION_BLOCKED`, `PHONE_DELIVERY_DELIVERED`, `PHONE_DELIVERY_UNDELIVERABLE`, `VALID_CODE_ENTERED`, `INVALID_CODE_ENTERED`, `PHONE_VERIFICATION_APPROVED`, `PHONE_VERIFICATION_DECLINED`, `PHONE_VERIFICATION_IN_REVIEW`, `PHONE_VERIFICATION_EXPIRED`.",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "description": "Type d'événement."
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Date et heure de l'événement."
                    },
                    "details": {
                      "type": "object",
                      "nullable": true,
                      "description": "Payload spécifique à l'événement. Événements d'envoi : `{status, reason, channel, actual_channel}` (`actual_channel` est renseigné une fois la livraison confirmée). Événements de livraison : `{channel, status}`. Événements de saisie de code : `{code_tried, status}`. Événements de statut final : `null`, ou `{reason}` en cas de refus ou d'examen en cours."
                    },
                    "fee": {
                      "type": "number",
                      "description": "Montant en USD facturé pour cet événement. Non nul uniquement sur les événements d'envoi (le prix de la livraison) ; 0 pour les saisies de code, les confirmations de livraison et les événements de statut."
                    }
                  }
                }
              },
              "matches": {
                "type": "array",
                "description": "Autres sessions de votre application (KYC, KYB ou API) où le même numéro de téléphone a été utilisé par un utilisateur différent (`vendor_data` différent). Jusqu'à 5 entrées, avec en premier une correspondance synthétique issue d'une liste de blocage lorsqu'elle est présente (les correspondances dérivées de sessions conservent l'ordre de la requête). Tableau vide lorsqu'il n'y a aucune correspondance.",
                "items": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "ID de session de l'autre vérification ayant utilisé ce numéro de téléphone."
                    },
                    "session_number": {
                      "type": "integer",
                      "description": "Numéro séquentiel lisible par l'humain de cette session."
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "`vendor_data` de cette session."
                    },
                    "verification_date": {
                      "type": "string",
                      "description": "Date et heure de création de cette session (`YYYY-MM-DDTHH:MM:SSZ`)."
                    },
                    "phone_number": {
                      "type": "string",
                      "description": "Le numéro de téléphone correspondant."
                    },
                    "status": {
                      "type": "string",
                      "description": "Statut de cette session (par exemple, `Approved`, `Declined`, `In Progress`)."
                    },
                    "is_blocklisted": {
                      "type": "boolean",
                      "description": "Indique si le numéro de téléphone figure sur la liste de blocage de votre application."
                    },
                    "api_service": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pour les sessions de type API, l'API autonome qui l'a créée (par ex., `PHONE_VERIFICATION`) ; `null` pour les sessions de vérification régulières."
                    },
                    "source": {
                      "type": "string",
                      "description": "Emplacement où la correspondance a été trouvée. Généralement `session` ; une correspondance avec une liste de blocage via une entrée de liste d'organisation insère une correspondance synthétique avec `source: \"list_entry\"` et `session_id`/`session_number` à null."
                    }
                  }
                }
              },
              "phone_social": {
                "$ref": "#/components/schemas/PhoneSocialFootprint"
              },
              "phone_intelligence": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/PhoneIntelligence"
                  }
                ],
                "description": "Signaux d'intelligence téléphonique. Présent uniquement lorsque `enable_enrichment` valait `true` lors de la vérification."
              }
            }
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "`vendor_data` de la session de la vérification correspondante. `null` pour `Expired or Not Found`."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "description": "`metadata` de la session de la vérification correspondante. `null` pour `Expired or Not Found`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cette réponse de vérification."
          }
        }
      },
      "EmailVerificationSendResponse": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de session de la vérification. Un envoi `Retry` renvoie le même `request_id` que l'envoi initial. Cet identifiant apparaît dans la Business Console, est renvoyé à nouveau par un `POST /v3/email/check/` finalisé, et peut être transmis à `GET /v3/session/{sessionId}/decision/`."
          },
          "status": {
            "type": "string",
            "enum": [
              "Success",
              "Retry",
              "Undeliverable"
            ],
            "description": "`Success` — OTP envoyé par e-mail pour une nouvelle vérification (facturé). `Retry` — nouvel OTP envoyé par e-mail pour la vérification en attente créée par un envoi précédent (gratuit). `Undeliverable` — l'adresse n'a pas passé la validation de délivrabilité ou le message n'a pas pu être envoyé ; la vérification est immédiatement finalisée comme `Declined` et rien n'est facturé."
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "email_can_not_be_delivered",
              null
            ],
            "description": "`email_can_not_be_delivered` lorsque `status` est `Undeliverable` ; `null` dans le cas contraire."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Écho des `vendor_data` stockées sur la session (depuis le premier envoi)."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "description": "Écho des `metadata` stockées sur la session (depuis le premier envoi)."
          }
        }
      },
      "EmailVerificationCheckResponse": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Pour `Approved`/`Declined` : l'identifiant de session de la vérification correspondante — identique au `request_id` renvoyé par `POST /v3/email/send/`. Pour `Failed` et `Expired or Not Found` : un UUID aléatoire à usage unique qui ne pourra pas être consulté ultérieurement."
          },
          "status": {
            "type": "string",
            "enum": [
              "Approved",
              "Declined",
              "Failed",
              "Expired or Not Found"
            ],
            "description": "`Approved` — code correct, aucun risque de refus. `Declined` — définitif : un risque entraînant un refus a correspondu ou le nombre maximal de tentatives (3) a été épuisé. `Failed` — code erroné, tentatives restantes. `Expired or Not Found` — aucune vérification en attente pour cette adresse au cours des 5 dernières minutes."
          },
          "message": {
            "type": "string",
            "description": "Explication lisible par l'humain du résultat, incluant le nombre de tentatives restantes après un code erroné."
          },
          "email": {
            "type": "object",
            "nullable": true,
            "description": "Rapport d'e-mail complet. Présent (non null) uniquement pour les résultats finalisés (`Approved`/`Declined`) ; `null` pour `Failed` et absent pour `Expired or Not Found`.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "Approved",
                  "Declined",
                  "In Review",
                  "Not Finished",
                  "Expired"
                ],
                "description": "Statut final de la vérification de l'e-mail. Correspond au `status` de premier niveau pour les vérifications finalisées."
              },
              "email": {
                "type": "string",
                "format": "email",
                "description": "L'adresse e-mail vérifiée.",
                "example": "alice@example.com"
              },
              "is_breached": {
                "type": "boolean",
                "description": "`true` lorsque l'adresse apparaît dans des violations de données connues (recherche de renseignements sur les violations exécutée lors de la finalisation)."
              },
              "breaches": {
                "type": "array",
                "description": "Jusqu'aux 5 fuites de données connues les plus récentes contenant cette adresse. Tableau vide (ou omis) lorsque `is_breached` vaut `false`.",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Identifiant de la violation."
                    },
                    "domain": {
                      "type": "string",
                      "description": "Domaine du service compromis."
                    },
                    "breach_date": {
                      "type": "string",
                      "format": "date",
                      "description": "Date à laquelle la violation s'est produite."
                    },
                    "breach_emails_count": {
                      "type": "integer",
                      "description": "Nombre total de comptes exposés lors de la violation."
                    },
                    "description": {
                      "type": "string",
                      "description": "Description lisible par l'humain de la violation (peut contenir du balisage HTML)."
                    },
                    "logo_path": {
                      "type": "string",
                      "description": "URL du logo du service compromis."
                    },
                    "data_classes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Catégories de données exposées, en snake_case (par exemple, `email_addresses`, `passwords`)."
                    },
                    "is_verified": {
                      "type": "boolean",
                      "description": "Indique si la légitimité de la fuite a été vérifiée."
                    }
                  }
                }
              },
              "is_disposable": {
                "type": "boolean",
                "description": "`true` lorsque le domaine appartient à un fournisseur connu d'e-mails temporaires/jetables."
              },
              "is_undeliverable": {
                "type": "boolean",
                "description": "`true` lorsque l'adresse ne peut pas recevoir de messages (échec de la validation de syntaxe ou DNS/MX, ou message rejeté)."
              },
              "verification_attempts": {
                "type": "integer",
                "description": "Nombre d'envois d'OTP pour cette vérification (1, ou 2 après une nouvelle tentative)."
              },
              "verified_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure de saisie du code correct. `null` si la vérification n'a jamais été approuvée."
              },
              "warnings": {
                "type": "array",
                "description": "Avertissements de risque enregistrés pendant la vérification (doublon, compromis, jetable, non livrable, nombre maximal de tentatives dépassé, liste de blocage, etc.). Tableau vide lorsqu'il n'y en a aucun.",
                "items": {
                  "type": "object",
                  "properties": {
                    "feature": {
                      "type": "string",
                      "description": "Fonctionnalité ayant généré l'avertissement. Toujours `EMAIL` ici."
                    },
                    "risk": {
                      "type": "string",
                      "description": "Code de risque lisible par machine."
                    },
                    "additional_data": {
                      "type": "object",
                      "nullable": true,
                      "description": "Contexte spécifique au risque (par ex., l'identifiant de la session dupliquée pour les risques de doublon). `null` lorsque le risque ne comporte aucune donnée supplémentaire."
                    },
                    "log_type": {
                      "type": "string",
                      "enum": [
                        "error",
                        "warning",
                        "information"
                      ],
                      "description": "Gravité. Les risques `error` entraînent le refus de la vérification, `warning` la signale pour examen, et `information` est enregistrée sans affecter le statut."
                    },
                    "short_description": {
                      "type": "string",
                      "description": "Résumé du risque en une ligne, lisible par l'utilisateur."
                    },
                    "long_description": {
                      "type": "string",
                      "description": "Explication lisible par l'humain du risque."
                    }
                  }
                }
              },
              "lifecycle": {
                "type": "array",
                "description": "Piste d'audit chronologique de la vérification. L'événement `type` est l'un des suivants : `EMAIL_VERIFICATION_MESSAGE_SENT`, `EMAIL_VERIFICATION_RETRY_MESSAGE_SENT`, `VALID_CODE_ENTERED`, `INVALID_CODE_ENTERED`, `EMAIL_VERIFICATION_APPROVED`, `EMAIL_VERIFICATION_DECLINED`, `EMAIL_VERIFICATION_IN_REVIEW`, `EMAIL_VERIFICATION_EXPIRED`.",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "description": "Type d'événement."
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Date et heure de l'événement."
                    },
                    "details": {
                      "type": "object",
                      "nullable": true,
                      "description": "Payload spécifique à l'événement. Événements d'envoi : `{status, reason}`. Événements de saisie de code : `{code_tried, status}`. Événements de statut final : `null`, ou `{reason}` en cas de refus ou d'examen en cours."
                    },
                    "fee": {
                      "type": "number",
                      "description": "Montant en USD facturé pour cet événement. Non nul uniquement lors du premier envoi réussi ; 0 pour les nouvelles tentatives, les saisies de code et les événements de statut."
                    }
                  }
                }
              },
              "matches": {
                "type": "array",
                "description": "Autres sessions de votre application (KYC, KYB ou API) où la même adresse e-mail a été utilisée par un utilisateur différent (`vendor_data` différent). Jusqu'à 5 entrées ; une correspondance synthétique issue d'une entrée de liste de blocage est ajoutée en tête lorsqu'elle existe (et uniquement lorsqu'aucune adresse e-mail issue d'une session et placée sur liste de blocage n'existe) — les correspondances issues d'une session conservent l'ordre de created_at. Tableau vide lorsqu'il n'y a aucune correspondance.",
                "items": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "ID de session de l'autre vérification ayant utilisé cette adresse e-mail."
                    },
                    "session_number": {
                      "type": "integer",
                      "description": "Numéro séquentiel lisible par l'humain de cette session."
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "`vendor_data` de cette session."
                    },
                    "verification_date": {
                      "type": "string",
                      "description": "Date et heure de création de cette session (`YYYY-MM-DDTHH:MM:SSZ`)."
                    },
                    "email": {
                      "type": "string",
                      "description": "L'adresse e-mail correspondante."
                    },
                    "status": {
                      "type": "string",
                      "description": "Statut de cette session (par exemple, `Approved`, `Declined`, `In Progress`)."
                    },
                    "is_blocklisted": {
                      "type": "boolean",
                      "description": "Indique si l'adresse e-mail figure sur la liste de blocage de votre application."
                    },
                    "api_service": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pour les sessions de type API, l'API autonome qui l'a créée (par ex., `PHONE_VERIFICATION`) ; `null` pour les sessions de vérification régulières."
                    },
                    "source": {
                      "type": "string",
                      "description": "Emplacement où la correspondance a été trouvée. Généralement `session` ; une correspondance avec une liste de blocage via une entrée de liste d'organisation insère une correspondance synthétique avec `source: \"list_entry\"` et `session_id`/`session_number` à null."
                    }
                  }
                }
              },
              "email_social": {
                "$ref": "#/components/schemas/EmailSocialFootprint"
              },
              "email_intelligence": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EmailIntelligence"
                  }
                ],
                "description": "Signaux d'analyse de l'e-mail. Présents uniquement lorsque `enable_enrichment` valait `true` lors de la vérification."
              }
            }
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "`vendor_data` de la session de la vérification correspondante. `null` pour `Expired or Not Found`."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "description": "`metadata` de la session de la vérification correspondante. `null` pour `Expired or Not Found`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cette réponse de vérification."
          }
        }
      },
      "WorkflowListItem": {
        "type": "object",
        "description": "Une version de workflow dans la vue en liste.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID par version. À utiliser comme `{settings_uuid}` pour la consultation, la mise à jour et la suppression, et comme `workflow_id` lors de la création de sessions."
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de groupe stable partagé par toutes les versions d'un même workflow. Égal à `uuid` pour la version 1."
          },
          "workflow_label": {
            "type": "string",
            "description": "Nom d'affichage du workflow."
          },
          "workflow_type": {
            "type": "string",
            "nullable": true,
            "description": "Type de base pour les workflows simples : `kyc`, `kyb`, `adaptive_age_verification`, `biometric_authentication`, etc. `null` pour les workflows basés sur un graphe sans fonctionnalité KYB."
          },
          "is_default": {
            "type": "boolean",
            "description": "Indique s'il s'agit du workflow par défaut pour les nouvelles sessions."
          },
          "is_archived": {
            "type": "boolean"
          },
          "is_white_label_enabled": {
            "type": "boolean",
            "description": "Indique si la personnalisation en marque blanche s'applique aux sessions créées avec ce workflow."
          },
          "total_price": {
            "type": "number",
            "description": "Prix fixe par vérification en USD (nombre JSON, exclut les fonctionnalités à tarification variable telles que DATABASE_VALIDATION et PHONE_VERIFICATION)."
          },
          "min_price": {
            "type": "number",
            "description": "Prix fixe le moins cher parmi les chemins du graphe de workflow, en USD."
          },
          "max_price": {
            "type": "number",
            "description": "Prix fixe le plus élevé parmi les chemins du graphe de workflow, en USD."
          },
          "features": {
            "type": "string",
            "description": "Fonctionnalités activées sous forme d'une chaîne unique jointe par `\" + \"`, par ex. `\"OCR + LIVENESS + FACE_MATCH\"`. Séparez la chaîne selon `\" + \"` pour obtenir une liste."
          },
          "is_simple_workflow": {
            "type": "boolean",
            "description": "Vrai lorsque le workflow ne dispose pas de graphe de workflow personnalisé."
          },
          "is_editable": {
            "type": "boolean",
            "description": "Vrai lorsque cette version est un `draft` (les brouillons sont modifiables directement ; les versions publiées sont immuables dans la Console)."
          },
          "workflow_url": {
            "type": "string",
            "format": "uri",
            "description": "URL de vérification publique et partageable pour ce workflow (`https://verify.didit.me/u/<token>`)."
          },
          "max_retry_attempts": {
            "type": "integer",
            "description": "Nombre maximal de tentatives de réessai autorisées après une vérification refusée (0-10)."
          },
          "retry_window_days": {
            "type": "integer",
            "nullable": true,
            "description": "Fenêtre glissante en jours utilisée pour compter les nouvelles tentatives (1-365). `null` = limite globale depuis le début."
          },
          "session_expiration_time": {
            "type": "integer",
            "description": "Secondes avant l'expiration d'une session inachevée (3600-2419200)."
          },
          "version": {
            "type": "integer",
            "description": "Numéro de version au sein du groupe `workflow_id`, commençant à 1."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published"
            ],
            "description": "Statut de la version. Les nouvelles sessions utilisent la dernière version `published` d'un groupe."
          },
          "has_draft": {
            "type": "boolean",
            "description": "Vrai lorsqu'une version de ce groupe `workflow_id` est actuellement un brouillon."
          },
          "created_by": {
            "type": "object",
            "nullable": true,
            "description": "Qui a créé cette version : `{name, email, type}` où `type` est `user` (utilisateur de la Console, `email` renseigné) ou `api_key` (`name` est l'identifiant client, `email` est null). `null` lorsqu'aucun créateur n'a été enregistré.",
            "properties": {
              "name": {
                "type": "string"
              },
              "email": {
                "type": "string",
                "nullable": true
              },
              "type": {
                "type": "string",
                "enum": [
                  "user",
                  "api_key"
                ]
              }
            }
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SimpleWorkflowRequest": {
        "type": "object",
        "description": "Créez un workflow linéaire simple. L'API convertit en interne cette liste de fonctionnalités en un graphe de workflow basé sur des nœuds. Liste blanche de champs STRICTE : toute clé non répertoriée ici (y compris `workflow_type`) est rejetée avec une erreur 400.",
        "required": [
          "features"
        ],
        "properties": {
          "workflow_label": {
            "type": "string",
            "maxLength": 50,
            "default": "ID Verification",
            "description": "Nom d'affichage du workflow (50 caractères maximum). La valeur par défaut est `\"ID Verification\"` lorsqu'il est omis — définissez-le toujours pour que les workflows restent faciles à distinguer.",
            "example": "Standard KYC"
          },
          "is_default": {
            "type": "boolean",
            "description": "Définir ce workflow comme celui par défaut pour les nouvelles sessions."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published"
            ],
            "description": "Omettez ce champ pour créer un workflow publié et prêt pour les sessions. Utilisez `draft` uniquement si vous souhaitez enregistrer sans publier."
          },
          "features": {
            "type": "array",
            "minItems": 1,
            "description": "Fonctionnalités de vérification dans l'ordre d'exécution. L'API relie automatiquement chaque élément au suivant et ajoute un nœud de statut final.",
            "items": {
              "$ref": "#/components/schemas/SimpleWorkflowFeature"
            }
          },
          "is_white_label_enabled": {
            "type": "boolean",
            "description": "Activer la personnalisation en marque blanche pour les sessions créées avec ce workflow.",
            "default": false
          },
          "is_desktop_allowed": {
            "type": "boolean",
            "description": "Autoriser l'exécution du flux de vérification sur les navigateurs sur ordinateur.",
            "default": false
          },
          "max_retry_attempts": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10,
            "default": 3,
            "description": "Nombre maximal de tentatives de réessai autorisées après une vérification refusée. `0` bloque l'utilisateur après le premier refus."
          },
          "retry_window_days": {
            "type": "integer",
            "minimum": 1,
            "maximum": 365,
            "nullable": true,
            "default": 7,
            "description": "Fenêtre glissante en jours utilisée pour compter les nouvelles tentatives. `null` applique une limite globale depuis le début."
          },
          "face_liveness_max_attempts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "default": 3,
            "description": "Nombre maximal de soumissions de détection du vivant par session. Par défaut 3 : une tentative initiale plus deux nouvelles tentatives. Cette valeur est également copiée dans les nœuds de workflow de détection du vivant et d'estimation de l'âge générés, sauf si la configuration au niveau de la fonctionnalité la remplace."
          },
          "face_match_max_attempts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "default": 3,
            "description": "Nombre maximal de soumissions de correspondance faciale par session. Par défaut 3 : une tentative initiale plus deux nouvelles tentatives. Cette valeur est également copiée dans les nœuds de workflow de correspondance faciale générés, sauf si la configuration au niveau de la fonctionnalité la remplace."
          },
          "session_expiration_time": {
            "type": "integer",
            "minimum": 3600,
            "maximum": 2419200,
            "default": 604800,
            "description": "Secondes avant l'expiration d'une session inachevée. Minimum 1 heure (3600), maximum 4 semaines (2419200)."
          }
        }
      },
      "SimpleWorkflowUpdateRequest": {
        "type": "object",
        "description": "Mettre à jour les métadonnées du workflow ou remplacer la liste complète des fonctionnalités linéaires. Liste blanche de champs STRICTE : toute clé non listée ici est rejetée avec un 400.",
        "properties": {
          "workflow_label": {
            "type": "string",
            "maxLength": 50,
            "description": "Nom d'affichage du workflow (50 caractères maximum)."
          },
          "is_default": {
            "type": "boolean",
            "description": "Définir ce workflow comme celui par défaut pour les nouvelles sessions."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published"
            ],
            "description": "Contrôle la gestion des versions. Omettez ce champ pour mettre à jour la version actuelle sur place (les brouillons sont publiés automatiquement). La valeur `published` sur une version déjà publiée crée et renvoie une NOUVELLE version. La valeur `draft` est uniquement valide tant que la version est encore un brouillon."
          },
          "features": {
            "type": "array",
            "minItems": 1,
            "description": "S'il est fourni, remplace l'ordre complet des fonctionnalités ainsi que leur configuration.",
            "items": {
              "$ref": "#/components/schemas/SimpleWorkflowFeature"
            }
          },
          "is_white_label_enabled": {
            "type": "boolean",
            "description": "Activer la personnalisation en marque blanche pour les sessions créées avec ce workflow."
          },
          "is_desktop_allowed": {
            "type": "boolean",
            "description": "Autoriser l'exécution du flux de vérification sur les navigateurs sur ordinateur."
          },
          "max_retry_attempts": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10,
            "description": "Nombre maximal de tentatives de réessai autorisées après une vérification refusée. `0` bloque l'utilisateur après le premier refus."
          },
          "retry_window_days": {
            "type": "integer",
            "minimum": 1,
            "maximum": 365,
            "nullable": true,
            "description": "Fenêtre glissante en jours utilisée pour compter les nouvelles tentatives. `null` applique une limite globale depuis le début."
          },
          "face_liveness_max_attempts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "description": "Nombre maximal de soumissions de détection du vivant par session. Cette valeur est également copiée dans les nœuds de workflow de détection du vivant et d'estimation de l'âge générés, sauf si la configuration au niveau de la fonctionnalité la remplace."
          },
          "face_match_max_attempts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "description": "Nombre maximal de soumissions de correspondance faciale par session. Cette valeur est également copiée dans les nœuds de workflow de correspondance faciale générés, sauf si la configuration au niveau de la fonctionnalité la remplace."
          },
          "session_expiration_time": {
            "type": "integer",
            "minimum": 3600,
            "maximum": 2419200,
            "description": "Secondes avant l'expiration d'une session inachevée. Minimum 1 heure (3600), maximum 4 semaines (2419200)."
          }
        }
      },
      "SimpleWorkflowFeature": {
        "type": "object",
        "required": [
          "feature"
        ],
        "properties": {
          "feature": {
            "type": "string",
            "description": "Fonctionnalité à exécuter. Utilisez les valeurs en majuscules indiquées ici.",
            "enum": [
              "OCR",
              "NFC",
              "LIVENESS",
              "FACE_MATCH",
              "PROOF_OF_ADDRESS",
              "QUESTIONNAIRE",
              "DOCUMENT_AI",
              "PHONE_VERIFICATION",
              "EMAIL_VERIFICATION",
              "DATABASE_VALIDATION",
              "AML",
              "IP_ANALYSIS",
              "AGE_ESTIMATION",
              "KYB_REGISTRY",
              "KYB_DOCUMENTS",
              "KYB_KEY_PEOPLE",
              "SIGNATURE"
            ]
          },
          "config": {
            "type": "object",
            "description": "Paramètres spécifiques à la fonctionnalité. Pour `QUESTIONNAIRE`, incluez `questionnaire_uuid` avec le `questionnaire_id` renvoyé par l'endpoint de création de questionnaire. Pour `SIGNATURE`, un workflow mis en production nécessite un document à signer : définissez `signature_documents_source` sur `session` ou `both` afin que chaque session puisse fournir le sien, ou envoyez `status: \"draft\"` et ajoutez les documents avant de publier. `signature_level: \"aes\"` est refusé avec `aes_not_available` tant que `signature_availability.aes` est `false` sur le workflow. Pour `OCR`, `methods` sélectionne les méthodes de vérification d'identité que chaque pays peut utiliser (capture de document, recherche sans document auprès d'une source gouvernementale ou d'une autre source faisant autorité, et portefeuilles d'identité numérique) ; omettez-le et chaque pays est configuré en capture de document uniquement. Pour `SIGNATURE`, consultez [Paramètres de signature électronique](/fr/management-api/workflows/feature-configs#signature-électronique) : `signature_level` accepte `simple` (par défaut, sans vérification d'identité requise ni e-mail ni téléphone requis) et `aes` pour le moment, et les documents de workflow ainsi que leurs champs sont gérés dans la console, donc via l'API, envoyez les documents et champs par session avec `signature_documents_source: \"session\"`.",
            "additionalProperties": true
          },
          "label": {
            "type": "string",
            "description": "Libellé interne optionnel pour ce nœud de workflow."
          }
        }
      },
      "ReviewItem": {
        "type": "object",
        "description": "Une entrée dans le flux d'examen / d'activité d'une session. Les changements de statut comportent `previous_status`, `new_status`, `previous_value`, `new_value` et `changed_fields` ; les commentaires comportent `comment` et (pour les commentaires de la Console) `mentioned_emails` ; les champs restants sont `null` ou vides lorsqu'ils ne s'appliquent pas au type d'activité.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de cette entrée de flux.",
            "example": "de0561bc-5583-4409-9171-1a31a4c8a5f4"
          },
          "activity_type": {
            "type": "string",
            "enum": [
              "COMMENT",
              "STATUS_UPDATED",
              "KYC_DATA_UPDATED",
              "POA_DATA_UPDATED",
              "FILE_ADDED",
              "FILE_REMOVED",
              "AML_ONGOING_MATCH",
              "AML_STATUS_UPDATED",
              "AML_HIT_STATUS_UPDATED",
              "KYB_DATA_UPDATED",
              "KYB_DOCUMENT_UPLOADED",
              "TAG_ADDED",
              "TAG_REMOVED",
              "FEATURE_OVERRIDE_PENDING",
              "FEATURE_OVERRIDE_APPLIED",
              "FEATURE_OVERRIDE_CANCELLED"
            ],
            "description": "Le type d'activité enregistré par cette entrée. Les lignes `STATUS_UPDATED` proviennent de décisions manuelles (`PATCH /v3/session/{session_id}/update-status/`) et d'entrées ajoutées via `POST …/reviews/` (qui prennent ce type par défaut même si aucun statut n'est enregistré). Les lignes `COMMENT` proviennent des réviseurs de la Console ; les consultations de la page de détails dans la Console sont également stockées sous forme de lignes `COMMENT` avec l'indicateur `metadata.system_event = \"DETAIL_VIEWED\"`. Les autres types assurent le suivi des modifications de données, des changements de fichiers, des tags et de l'activité de surveillance AML. Les lignes STATUS_UPDATED sont également écrites par des acteurs système (par exemple la surveillance AML continue avec un actor_type SYSTEM, et les mises à jour automatiques des statuts de fonctionnalités), et pas uniquement par l'endpoint update-status et les publications d'examen manuel. `FEATURE_OVERRIDE_PENDING`, `FEATURE_OVERRIDE_APPLIED` et `FEATURE_OVERRIDE_CANCELLED` enregistrent le remplacement du statut d'une vérification (`PATCH /v3/session/{session_id}/features/{node_id}/update-status/`) : demandé en attente de la fin du flux, appliqué ou annulé. Ils contiennent le statut de la vérification dans `previous_value` / `new_value` (`{\"status\": ...}`), laissent `previous_status` et `new_status` à `null`, et désignent le remplacement dans `metadata` (`feature_override_id`, `node_id`, `feature_model`, `forced`, `state`, `cancel_reason`). L'entrée de la demande contient le `comment` du réviseur ; un remplacement appliqué lorsque le flux se termine est enregistré avec un `actor_type` `SYSTEM`.",
            "example": "STATUS_UPDATED"
          },
          "actor_display": {
            "type": "string",
            "description": "Libellé d'auteur lisible par l'humain, résolu dans l'ordre : nom complet de l'acteur → identifiant du compte Console → partie locale de `actor_email` → `\"API Client\"` (pour les acteurs `API_KEY`) → `\"System\"` (pour les acteurs `SYSTEM`) → `\"Unknown\"`. Les entrées créées via `POST …/reviews/` affichent toujours `\"Unknown\"` car cet endpoint n'enregistre aucune attribution d'acteur.",
            "example": "API Client"
          },
          "actor_email": {
            "type": "string",
            "nullable": true,
            "description": "E-mail de l'utilisateur de la Console ayant effectué l'action. `null` pour les acteurs de type clé API et système.",
            "example": null
          },
          "actor_type": {
            "type": "string",
            "enum": [
              "API_KEY",
              "CONSOLE_USER",
              "SYSTEM"
            ],
            "description": "Qui a effectué l'action : une clé API, un utilisateur de la Console ou Didit lui-même (`SYSTEM`, par ex. la surveillance AML continue). Les entrées créées via `POST …/reviews/` portent la valeur par défaut `CONSOLE_USER`, quel que soit l'appelant.",
            "example": "API_KEY"
          },
          "new_status": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Not Started",
              "In Progress",
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned",
              "Kyc Expired",
              "Resubmitted",
              "Awaiting User"
            ],
            "description": "Statut de session enregistré par cette entrée (pour les mises à jour de statut). `null` pour les commentaires et les entrées de modification de données.",
            "example": "Approved"
          },
          "previous_status": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Not Started",
              "In Progress",
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned",
              "Kyc Expired",
              "Resubmitted",
              "Awaiting User"
            ],
            "description": "Statut de la session avant la modification. Renseigné sur les entrées `STATUS_UPDATED` écrites par l'endpoint de mise à jour du statut ; `null` sur les entrées ajoutées via `POST …/reviews/`. Également renseigné sur les lignes STATUS_UPDATED générées par le système.",
            "example": "In Review"
          },
          "comment": {
            "type": "string",
            "nullable": true,
            "description": "Note en texte libre associée à l'entrée, ou `null`.",
            "example": "Document re-checked manually; address matches."
          },
          "mentioned_emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            },
            "description": "Utilisateurs de la Console mentionnés avec `@email` dans le commentaire. Toujours vide pour les entrées créées via cette API — le traitement des mentions est une fonctionnalité réservée à la Console.",
            "example": []
          },
          "previous_value": {
            "type": "object",
            "nullable": true,
            "description": "Instantané des données modifiées avant l'action, par exemple `{\"status\": \"In Review\"}` lors d'un changement de statut. `null` lorsque rien n'a été modifié.",
            "example": {
              "status": "In Review"
            }
          },
          "new_value": {
            "type": "object",
            "nullable": true,
            "description": "Instantané des données modifiées après l'action, par exemple `{\"status\": \"Approved\"}`. `null` lorsque rien n'a été modifié.",
            "example": {
              "status": "Approved"
            }
          },
          "changed_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Noms des champs modifiés par cette activité (par ex. `[\"status\"]`). Vide pour les commentaires et pour les entrées ajoutées via `POST …/reviews/`.",
            "example": [
              "status"
            ]
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "description": "Contexte supplémentaire pour les entrées générées par le système. Les consultations de la page de détails de la Console comportent `{\"system_event\": \"DETAIL_VIEWED\", \"detail_type\": \"verification\"}` afin de pouvoir être exclues de la logique de notification. Un `COMMENT` modifié par son auteur dans la Console comporte `edited_at`, l'horodatage ISO 8601 de la dernière modification (`comment` et `mentioned_emails` contiennent alors le texte modifié et ses mentions). `null` pour les entrées ordinaires.",
            "example": null
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure d'écriture de l'entrée, ISO 8601 UTC.",
            "example": "2026-06-12T00:19:31.918735Z"
          }
        }
      },
      "QuestionnaireListItem": {
        "type": "object",
        "description": "Une version de questionnaire dans la vue en liste.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID par version. À utiliser comme `{questionnaire_uuid}` pour la consultation, la mise à jour et la suppression, ainsi que comme `questionnaire_uuid` dans la configuration de fonctionnalité QUESTIONNAIRE d'un workflow."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "default_language": {
            "type": "string"
          },
          "is_active": {
            "type": "boolean"
          },
          "is_simple_questionnaire": {
            "type": "boolean",
            "description": "Vrai pour les questionnaires linéaires créés via cette API ; faux pour les questionnaires basés sur un graphe créés dans la Console."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "question_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Types d'éléments en majuscules des questions auxquelles il est possible de répondre, dans l'ordre de création (par exemple `SHORT_TEXT`, `MULTIPLE_CHOICE`, `FILE_UPLOAD`). Les éléments structurels `SECTION_HEADER` et `SEPARATOR` sont exclus. Une entrée par question, les valeurs peuvent donc se répéter."
          },
          "workflow_names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Noms des workflows utilisant ce questionnaire. Actuellement toujours `[]` sur cet endpoint (renseigné uniquement dans la liste de la Console)."
          },
          "questionnaire_group_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant stable qui regroupe toutes les versions du même questionnaire."
          },
          "version": {
            "type": "integer",
            "description": "Numéro de version au sein du groupe, commençant à 1."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published"
            ]
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles cette version a été publiée. `null` pour les brouillons."
          },
          "is_editable": {
            "type": "boolean",
            "description": "Vrai lorsque cette version est un `draft`."
          }
        }
      },
      "SimpleQuestionnaireRequest": {
        "type": "object",
        "description": "Créez un questionnaire linéaire simple. L'API convertit `form_elements` en graphe interne du questionnaire.",
        "required": [
          "title",
          "languages",
          "form_elements"
        ],
        "properties": {
          "title": {
            "type": "string",
            "description": "Nom interne du questionnaire."
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "languages": {
            "type": "array",
            "description": "Langues incluses dans chaque libellé. Doit inclure `en`.",
            "items": {
              "type": "string"
            },
            "example": [
              "en"
            ]
          },
          "default_language": {
            "type": "string",
            "description": "Langue par défaut. Doit être incluse dans `languages`.",
            "example": "en"
          },
          "is_active": {
            "type": "boolean",
            "default": true
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published"
            ],
            "description": "Omettez ce champ pour créer un questionnaire publié et prêt pour les workflows."
          },
          "form_elements": {
            "type": "array",
            "minItems": 1,
            "description": "Questions dans l'ordre exact où les utilisateurs doivent les voir. Les embranchements et les champs conditionnels ne sont pas pris en charge.",
            "items": {
              "$ref": "#/components/schemas/SimpleQuestionnaireElement"
            }
          }
        }
      },
      "SimpleQuestionnaireUpdateRequest": {
        "type": "object",
        "description": "Mettre à jour les métadonnées du questionnaire ou remplacer la liste linéaire complète `form_elements`.",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "default_language": {
            "type": "string"
          },
          "is_active": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published"
            ]
          },
          "form_elements": {
            "type": "array",
            "minItems": 1,
            "description": "S'il est fourni, remplace la liste linéaire complète des questions.",
            "items": {
              "$ref": "#/components/schemas/SimpleQuestionnaireElement"
            }
          }
        }
      },
      "SimpleQuestionnaireElement": {
        "type": "object",
        "required": [
          "element_type",
          "label"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Identifiant de question stable optionnel. S'il est omis, l'API génère `q1`, `q2`, etc. Utilisez des lettres minuscules, des chiffres et des traits de soulignement pour une meilleure lisibilité.",
            "example": "source_of_funds"
          },
          "element_type": {
            "type": "string",
            "description": "Type de question. L'API accepte ces valeurs en minuscules ainsi que leurs équivalents en majuscules.",
            "enum": [
              "short_text",
              "long_text",
              "dropdown",
              "single_choice",
              "multiple_choice",
              "number",
              "image",
              "file_upload",
              "time",
              "email",
              "address",
              "phone",
              "country",
              "date_picker",
              "consent",
              "section_header",
              "separator",
              "heading",
              "paragraph"
            ]
          },
          "label": {
            "type": "object",
            "description": "Libellé de la question par code de langue, par exemple `{ \"en\": \"Source of funds\" }`.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "description": {
            "type": "object",
            "nullable": true,
            "additionalProperties": {
              "type": "string"
            }
          },
          "placeholder": {
            "type": "object",
            "nullable": true,
            "additionalProperties": {
              "type": "string"
            }
          },
          "is_required": {
            "type": "boolean",
            "default": false
          },
          "options": {
            "type": "array",
            "description": "À utiliser pour `dropdown`, `single_choice` et `multiple_choice`. Si `value` est omis, l'API en génère un à partir du libellé de l'option.",
            "items": {
              "type": "object",
              "required": [
                "label"
              ],
              "properties": {
                "value": {
                  "type": "string"
                },
                "label": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "max_files": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5,
            "description": "À utiliser avec `file_upload` ou `image`."
          },
          "validation": {
            "type": "object",
            "nullable": true,
            "description": "Validation de format optionnelle pour `short_text`, `long_text` ou `number`. Appliquée pendant que l'utilisateur remplit le champ (il ne peut pas continuer tant qu'elle n'est pas validée) et vérifiée de nouveau par l'API lors de l'envoi.",
            "properties": {
              "pattern": {
                "type": "string",
                "description": "Expression régulière (sous-ensemble ECMA-262) à laquelle la valeur doit correspondre entièrement. Pour `short_text` et `long_text`. N'ajoutez pas d'ancres ^/$ ; la valeur entière est mise en correspondance."
              },
              "min_length": {
                "type": "integer",
                "minimum": 0,
                "description": "Nombre minimum de caractères. Pour `short_text` et `long_text`."
              },
              "max_length": {
                "type": "integer",
                "minimum": 0,
                "description": "Nombre maximal de caractères. Pour `short_text` et `long_text`."
              },
              "min": {
                "type": "number",
                "description": "Valeur numérique minimale. Pour `number`."
              },
              "max": {
                "type": "number",
                "description": "Valeur numérique maximale. Pour `number`."
              },
              "error_message": {
                "type": "object",
                "description": "Message traduit affiché en cas d'échec de validation, indexé par code de langue.",
                "additionalProperties": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "QuestionnaireDetail": {
        "type": "object",
        "description": "Détails complets du questionnaire renvoyés par les endpoints GET, POST (création) et PATCH (mise à jour).",
        "properties": {
          "questionnaire_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du questionnaire. Utilisez cet identifiant pour faire référence au questionnaire depuis un workflow ou lors de requêtes ultérieures de mise à jour ou de suppression."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "default_language": {
            "type": "string"
          },
          "is_active": {
            "type": "boolean"
          },
          "is_simple_questionnaire": {
            "type": "boolean"
          },
          "graph": {
            "type": "object",
            "description": "Structure en graphe avec start_node et la table de correspondance des nœuds."
          },
          "sections": {
            "type": "array",
            "description": "Contenu du questionnaire regroupé en sections (dérivé du graphe).",
            "items": {
              "type": "object"
            }
          },
          "questionnaire_group_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant stable qui regroupe toutes les versions du même questionnaire."
          },
          "version": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published"
            ]
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "is_editable": {
            "type": "boolean",
            "description": "Vrai lorsque le questionnaire peut encore être modifié directement (versions brouillon)."
          }
        }
      },
      "UserListItem": {
        "type": "object",
        "description": "Un utilisateur vérifié.",
        "properties": {
          "didit_internal_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID interne stable de Didit pour cet utilisateur."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre identifiant unique pour cet utilisateur (transmis lors de la création des sessions). Peut être nul si aucun identifiant fournisseur n'a été fourni."
          },
          "display_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom d'affichage personnalisé défini par vous"
          },
          "full_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom complet extrait des documents vérifiés"
          },
          "date_of_birth": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "effective_name": {
            "type": "string",
            "nullable": true,
            "description": "Meilleur nom disponible : display_name s'il est défini, sinon full_name"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "FLAGGED",
              "BLOCKED"
            ],
            "description": "Statut de cycle de vie de l'enregistrement utilisateur (PAS un statut de session). `ACTIVE` est la valeur par défaut, `FLAGGED` signale l'utilisateur pour un examen manuel, `BLOCKED` empêche de nouvelles sessions pour ce `vendor_data`."
          },
          "portrait_image_url": {
            "type": "string",
            "nullable": true,
            "description": "URL pré-signée de la photo de portrait de l'utilisateur (expire après quelques heures)"
          },
          "session_count": {
            "type": "integer",
            "description": "Nombre total de sessions de vérification pour cet utilisateur"
          },
          "approved_count": {
            "type": "integer",
            "description": "Nombre de sessions approuvées"
          },
          "declined_count": {
            "type": "integer",
            "description": "Nombre de sessions refusées"
          },
          "in_review_count": {
            "type": "integer",
            "description": "Nombre de sessions en cours d'examen"
          },
          "issuing_states": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Codes ISO 3166-1 alpha-3 des pays de délivrance observés sur les documents d'identité approuvés de cet utilisateur, par ex. `[\"USA\", \"ESP\"]`. Tableau vide s'il n'y en a aucun."
          },
          "approved_emails": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Adresses e-mail vérifiées collectées à partir des sessions approuvées de cet utilisateur, par ex. `[\"john@example.com\"]`."
          },
          "approved_phones": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Numéros de téléphone vérifiés collectés à partir des sessions approuvées de cet utilisateur, par ex. `[\"+14155551234\"]`."
          },
          "features": {
            "type": "object",
            "description": "Statut agrégé par fonctionnalité sur l'ensemble des sessions de cet utilisateur. Clés possibles : `ID_VERIFICATION`, `NFC`, `LIVENESS`, `FACE_MATCH`, `POA`, `QUESTIONNAIRE`, `EMAIL_VERIFICATION`, `PHONE`, `AML`, `IP_ANALYSIS`, `AGE_ESTIMATION`, `DATABASE_VALIDATION`. Valeurs possibles : `Approved`, `Declined`, `In Review`, `Not Finished`, `Resub Requested`."
          },
          "features_list": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "feature": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                }
              }
            },
            "description": "Mêmes données que `features`, sous la forme d'un tableau ordonné d'objets `{feature, status}`."
          },
          "last_session_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage de la session la plus récente"
          },
          "first_session_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage de la première session"
          },
          "last_activity_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage de l'activité la plus récente sur cet utilisateur (session, transaction, changement de statut, modification des données, etc.)."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "color": {
                  "type": "string"
                }
              }
            },
            "description": "Tags attribués à cet utilisateur"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BlocklistItem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "face",
              "document",
              "phone",
              "email"
            ]
          },
          "session_id": {
            "type": "string",
            "format": "uuid"
          },
          "session_number": {
            "type": "integer"
          },
          "blocklisted_at": {
            "type": "string",
            "format": "date-time"
          },
          "face_image": {
            "type": "string",
            "nullable": true
          },
          "document_type": {
            "type": "string",
            "nullable": true
          },
          "document_number": {
            "type": "string",
            "nullable": true
          },
          "phone_number": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "UserDetailItem": {
        "type": "object",
        "description": "Détails complets de l'utilisateur. Étend UserListItem avec les métadonnées, les commentaires et updated_at.",
        "allOf": [
          {
            "$ref": "#/components/schemas/UserListItem"
          },
          {
            "type": "object",
            "properties": {
              "metadata": {
                "type": "object",
                "description": "JSON de métadonnées personnalisées que vous avez associé à cet utilisateur. La valeur par défaut est `{}`."
              },
              "tags": {
                "type": "array",
                "description": "Attributions de tags. REMARQUE : sur les réponses détaillées, chaque entrée est un objet de *liaison* de tag (`{uuid, tag: {...}, added_by_email, added_by_name, created_at}`), contrairement au format plat `{uuid, name, color}` utilisé sur les réponses de liste.",
                "items": {
                  "type": "object",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid",
                      "description": "UUID de l'attribution du tag (et non le tag lui-même)."
                    },
                    "tag": {
                      "type": "object",
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "color": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string",
                          "nullable": true
                        },
                        "source": {
                          "type": "string",
                          "enum": [
                            "didit",
                            "custom"
                          ]
                        },
                        "created_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "updated_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    },
                    "added_by_email": {
                      "type": "string",
                      "nullable": true
                    },
                    "added_by_name": {
                      "type": "string",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              },
              "comments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "comment_type": {
                      "type": "string",
                      "enum": [
                        "COMMENT",
                        "STATUS_CHANGED",
                        "METADATA_UPDATED",
                        "TAG_ADDED",
                        "TAG_REMOVED",
                        "PROFILE_UPDATED"
                      ]
                    },
                    "comment": {
                      "type": "string",
                      "nullable": true
                    },
                    "actor_email": {
                      "type": "string",
                      "nullable": true
                    },
                    "actor_name": {
                      "type": "string",
                      "nullable": true
                    },
                    "previous_status": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "ACTIVE",
                        "FLAGGED",
                        "BLOCKED",
                        null
                      ]
                    },
                    "new_status": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "ACTIVE",
                        "FLAGGED",
                        "BLOCKED",
                        null
                      ]
                    },
                    "previous_value": {
                      "type": "object",
                      "nullable": true,
                      "description": "Valeurs précédentes des champs pour les entrées PROFILE_UPDATED."
                    },
                    "new_value": {
                      "type": "object",
                      "nullable": true,
                      "description": "Nouvelles valeurs de champ pour les entrées PROFILE_UPDATED."
                    },
                    "changed_fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Noms des champs modifiés par une entrée PROFILE_UPDATED."
                    },
                    "metadata": {
                      "type": "object",
                      "nullable": true
                    },
                    "mentioned_emails": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "description": "Journal d'activité et commentaires pour cet utilisateur (changements de statut, modifications de profil, notes manuelles)."
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ]
      },
      "BusinessListItem": {
        "type": "object",
        "description": "Une entreprise vérifiée.",
        "properties": {
          "didit_internal_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID interne stable de Didit pour cette entreprise."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre identifiant unique pour cette entreprise (transmis lors de la création des sessions). Peut être nul si aucun identifiant fournisseur n'a été fourni."
          },
          "display_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom d'affichage personnalisé défini par vous"
          },
          "legal_name": {
            "type": "string",
            "nullable": true,
            "description": "Raison sociale officielle issue du registre ou saisie manuelle"
          },
          "registration_number": {
            "type": "string",
            "nullable": true,
            "description": "Numéro d'immatriculation ou de constitution de l'entreprise"
          },
          "country_code": {
            "type": "string",
            "nullable": true,
            "description": "Pays de constitution (ISO 3166-1 alpha-2, par ex. `GB`, `US`)."
          },
          "effective_name": {
            "type": "string",
            "nullable": true,
            "description": "Meilleur nom disponible : display_name s'il est défini, sinon legal_name"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "FLAGGED",
              "BLOCKED"
            ],
            "description": "Statut de cycle de vie de l'enregistrement d'entreprise (PAS un statut de session). `ACTIVE` est la valeur par défaut, `FLAGGED` le signale pour un examen manuel, `BLOCKED` empêche de nouvelles sessions pour ce `vendor_data`."
          },
          "session_count": {
            "type": "integer",
            "description": "Nombre total de sessions de vérification pour cette entreprise"
          },
          "approved_count": {
            "type": "integer",
            "description": "Nombre de sessions approuvées"
          },
          "declined_count": {
            "type": "integer",
            "description": "Nombre de sessions refusées"
          },
          "in_review_count": {
            "type": "integer",
            "description": "Nombre de sessions en cours d'examen"
          },
          "features": {
            "type": "object",
            "description": "Statut agrégé par fonctionnalité sur l'ensemble des sessions KYB de cette entreprise. Actuellement, la seule clé est `KYB` (le statut de vérification de l'entreprise au registre). Valeurs possibles : `Approved`, `Declined`, `In Review`, `Not Finished`, `Resub Requested`."
          },
          "features_list": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "feature": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                }
              }
            },
            "description": "Mêmes données que `features`, sous la forme d'un tableau ordonné d'objets `{feature, status}`."
          },
          "last_session_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage de la session la plus récente"
          },
          "first_session_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage de la première session"
          },
          "last_activity_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage de l'activité la plus récente (changement de statut, mise à jour de la session, etc.)"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "color": {
                  "type": "string"
                }
              }
            },
            "description": "Tags attribués à cette entreprise"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BusinessDetailItem": {
        "type": "object",
        "description": "Détails complets de l'entreprise. Étend BusinessListItem avec métadonnées et updated_at.",
        "allOf": [
          {
            "$ref": "#/components/schemas/BusinessListItem"
          },
          {
            "type": "object",
            "properties": {
              "metadata": {
                "type": "object",
                "description": "JSON de métadonnées personnalisées que vous avez associé à cette entreprise. La valeur par défaut est `{}`."
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ]
      },
      "TransactionDetail": {
        "type": "object",
        "description": "Enregistrement de surveillance complet pour une transaction, tel que renvoyé par `GET /v3/transactions/{transaction_id}/` et `POST /v3/transactions/`.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de transaction stable attribué par Didit. À utiliser comme `{transaction_id}` pour les appels de suivi."
          },
          "environment": {
            "type": "string",
            "enum": [
              "live",
              "sandbox"
            ],
            "description": "Environnement de l'application propriétaire de la transaction. Une transaction `sandbox` est enregistrée mais n'est jamais évaluée, filtrée, notifiée ou facturée, de sorte que son `rule_runs` vide signifie « non évaluée »."
          },
          "transaction_number": {
            "type": "integer",
            "description": "Numéro de transaction séquentiel propre à l'application affiché dans la console (ex. `4123`)."
          },
          "txn_id": {
            "type": "string",
            "description": "Le `transaction_id` que vous avez fourni lors de la création (128 caractères max.). Unique par application."
          },
          "txn_date": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles la transaction a eu lieu (à partir de `transaction_at` ; par défaut, la date de soumission)."
          },
          "zone_id": {
            "type": "string",
            "nullable": true,
            "description": "Identifiant de fuseau horaire IANA fourni au moment de la création."
          },
          "transaction_type": {
            "type": "string",
            "description": "Catégorie de premier niveau telle que stockée : `finance`, `kyc`, `travelRule`, `userPlatformEvent`, `gamblingBet`, `gamblingLimitChange`, `gamblingBonusChange`, `auditTrailEvent`. Notez que les valeurs composées de plusieurs mots sont renvoyées en camelCase même lorsqu'elles ont été transmises en snake_case."
          },
          "action_type": {
            "type": "string",
            "description": "Sous-type au sein de la catégorie (par exemple `deposit`, `withdrawal`, `transfer`). Correspond par défaut à la catégorie s'il n'est pas fourni."
          },
          "direction": {
            "type": "string",
            "enum": [
              "INBOUND",
              "OUTBOUND"
            ],
            "description": "Direction relative au sujet. Stockée en majuscules quelle que soit la casse fournie (`in`/`out`/`inbound`/`outbound` sont acceptés en entrée)."
          },
          "status": {
            "type": "string",
            "enum": [
              "APPROVED",
              "IN_REVIEW",
              "DECLINED",
              "AWAITING_USER"
            ],
            "description": "Verdict actuel de la surveillance. Les transactions sont créées avec le statut `APPROVED` ; les règles peuvent les faire basculer vers `IN_REVIEW`/`DECLINED` de manière synchrone."
          },
          "source": {
            "type": "string",
            "enum": [
              "LIVE",
              "IMPORTED"
            ],
            "description": "Origine de l'enregistrement : `LIVE` pour les transactions soumises via l'API ou le SDK, `IMPORTED` pour les transactions chargées via l'import de la console."
          },
          "amount": {
            "type": "string",
            "description": "Montant de la transaction sous forme de chaîne décimale sans les zéros de fin (par ex. `\"1500\"`, `\"0.5\"`, `\"0.123456789012345678\"`). Jusqu'à 18 décimales."
          },
          "currency": {
            "type": "string",
            "description": "Code devise de `amount`. Tout code alphabétique ISO 4217 est accepté (par ex. `EUR`, `USD`, `NGN`), ainsi qu'un symbole d'actif crypto (par ex. `BTC`). Privilégiez un code actuellement en circulation. Tous les codes acceptés ne disposent pas d'un taux de change : lorsqu'aucun taux n'est disponible pour le code (par exemple l'unité de compte ISO `XSU`, ou un symbole crypto dont Didit n'établit pas le prix), la conversion automatique échoue et `preferred_currency_amount` est retourné nul, sauf si la requête a fourni un montant pré-converti `amount_in_default_currency`."
          },
          "currency_type": {
            "type": "string",
            "nullable": true,
            "description": "`fiat` ou `crypto`, selon la valeur fournie dans `currency_kind`."
          },
          "amount_in_default_currency": {
            "type": "string",
            "nullable": true,
            "description": "Montant pré-converti que vous avez fourni, sous forme de chaîne décimale sans les zéros de fin."
          },
          "default_currency_code": {
            "type": "string",
            "nullable": true
          },
          "preferred_currency_amount": {
            "type": "string",
            "nullable": true,
            "description": "`amount` converti dans la devise préférée de l'application, lorsqu'il est disponible."
          },
          "preferred_currency_code": {
            "type": "string",
            "nullable": true
          },
          "payment_details": {
            "type": "string",
            "nullable": true,
            "description": "Référence ou mémo de paiement en texte libre issu de la soumission."
          },
          "payment_txn_id": {
            "type": "string",
            "nullable": true,
            "description": "Référence du système de paiement externe (par ex. hachage de transaction blockchain) issue de `payment_reference_id`."
          },
          "score": {
            "type": "integer",
            "description": "Score de risque cumulé par les règles (généralement 0–100). Plus il est élevé, plus le risque est grand."
          },
          "severity": {
            "type": "string",
            "nullable": true,
            "enum": [
              "UNKNOWN",
              "LOW",
              "MEDIUM",
              "HIGH",
              "CRITICAL"
            ],
            "description": "Gravité catégorielle du risque définie par les règles/fournisseurs (`UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`). `null` jusqu'à ce qu'un élément la définisse."
          },
          "decision_reason_code": {
            "type": "string",
            "nullable": true,
            "description": "Raison lisible par machine pour le `status` actuel."
          },
          "decision_reason_label": {
            "type": "string",
            "nullable": true,
            "description": "Libellé lisible par l'humain pour `decision_reason_code`."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Copie de commodité des `vendor_data` du demandeur."
          },
          "metadata": {
            "type": "object",
            "description": "Instantané des payloads `subject` et `counterparty` tels qu'ils ont été soumis au moment de la création."
          },
          "props": {
            "type": "object",
            "description": "Les `custom_properties` fournies lors de la création. Chaque clé est accessible dans les conditions de règles sous la forme `custom_values.<key>`."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "color": {
                  "type": "string"
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "didit",
                    "custom"
                  ],
                  "description": "Indique si le tag est un préréglage Didit ou un tag personnalisé."
                }
              }
            },
            "description": "Tags associés à la transaction (manuellement ou par des règles)."
          },
          "parties": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "role": {
                  "type": "string",
                  "enum": [
                    "APPLICANT",
                    "REMITTER",
                    "BENEFICIARY",
                    "COUNTERPARTY"
                  ],
                  "description": "Rôle de la partie. L'endpoint de création attribue `APPLICANT` (le sujet) et `COUNTERPARTY`."
                },
                "entity_type": {
                  "type": "string",
                  "enum": [
                    "individual",
                    "company",
                    "external",
                    "unhostedWallet"
                  ]
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "USER",
                    "BUSINESS",
                    "EXTERNAL"
                  ],
                  "description": "Les parties `USER`/`BUSINESS` renvoient à une entité appartenant à Didit via `vendor_data`. Les parties `EXTERNAL` n'ont aucune entité Didit derrière elles."
                },
                "vendor_data": {
                  "type": "string",
                  "nullable": true,
                  "description": "Votre identifiant interne d'utilisateur/entreprise."
                },
                "full_name": {
                  "type": "string",
                  "nullable": true
                },
                "first_name": {
                  "type": "string",
                  "nullable": true
                },
                "last_name": {
                  "type": "string",
                  "nullable": true
                },
                "country_code": {
                  "type": "string",
                  "nullable": true,
                  "description": "Code pays issu de `address.country` fourni (généralement ISO 3166-1 alpha-3)."
                },
                "dob": {
                  "type": "string",
                  "format": "date",
                  "nullable": true,
                  "description": "Date de naissance issue du `date_of_birth` soumis."
                },
                "address": {
                  "type": "object",
                  "description": "Objet d'adresse tel qu'il a été soumis. `{}` s'il est omis."
                },
                "institution_info": {
                  "type": "object",
                  "description": "Informations sur l'établissement telles que soumises. `{}` lorsqu'elles sont omises."
                },
                "device": {
                  "type": "object",
                  "description": "Contexte d'appareil normalisé, incluant l'enrichissement de l'IP côté serveur sous network_context (géolocalisation, indicateurs VPN/centre de données) lorsqu'une adresse IP a été fournie.",
                  "properties": {
                    "fingerprint": {
                      "type": "string",
                      "description": "Empreinte unique de l'appareil."
                    },
                    "persistent_device_id": {
                      "type": "string",
                      "description": "Identifiant stable de l'appareil entre les sessions (schéma d'empreinte v2)."
                    },
                    "user_agent": {
                      "type": "string",
                      "description": "Chaîne de l'agent utilisateur du navigateur ou de l'application."
                    },
                    "browser_family": {
                      "type": "string",
                      "description": "Famille du navigateur (ex. Chrome, Firefox, Safari)."
                    },
                    "browser_version": {
                      "type": "string",
                      "description": "Chaîne de version du navigateur."
                    },
                    "platform": {
                      "type": "string",
                      "description": "Identifiant de plateforme (web, ios, android, macos, windows, linux)."
                    },
                    "os_family": {
                      "type": "string",
                      "description": "Famille de système d'exploitation (par exemple iOS, Android, Windows)."
                    },
                    "os_version": {
                      "type": "string",
                      "description": "Chaîne de version du système d'exploitation."
                    },
                    "accept_language": {
                      "type": "string",
                      "description": "Valeur de l'en-tête Accept-Language."
                    },
                    "session_id": {
                      "type": "string",
                      "description": "Identifiant de session (stocké dans les métadonnées)."
                    },
                    "session_age_ms": {
                      "type": "number",
                      "description": "Âge de la session en millisecondes."
                    },
                    "network_context": {
                      "type": "object",
                      "description": "Contexte réseau avec adresse IP et géolocalisation.",
                      "properties": {
                        "ip_address": {
                          "type": "string",
                          "description": "Adresse du client."
                        },
                        "ip_country_code": {
                          "type": "string",
                          "description": "Pays déterminé par géolocalisation de l'IP (ISO 3166-1 alpha-3)."
                        },
                        "latitude": {
                          "type": "number",
                          "description": "Latitude géographique de l'IP."
                        },
                        "longitude": {
                          "type": "number",
                          "description": "Longitude géographique de l'IP."
                        }
                      }
                    }
                  }
                },
                "external_party_snapshot": {
                  "type": "object",
                  "nullable": true,
                  "description": "Copie figée des données de la partie pour les parties `EXTERNAL`. `null` tant que la partie est liée à un utilisateur ou une entreprise Didit."
                }
              }
            },
            "description": "Parties à la transaction (demandeur, contrepartie)."
          },
          "payment_methods": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "payment_method_type": {
                  "type": "string",
                  "enum": [
                    "bank_card",
                    "bank_account",
                    "e_wallet",
                    "crypto_wallet",
                    "unhosted_wallet",
                    "other"
                  ]
                },
                "label": {
                  "type": "string",
                  "nullable": true
                },
                "fingerprint": {
                  "type": "string",
                  "nullable": true,
                  "description": "SHA-256 sur `type:account_id:issuing_country` — identifiant stable pour corréler la réutilisation d'un même instrument."
                },
                "account_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identifiant de compte (IBAN, adresse de portefeuille, token de carte, …)."
                },
                "issuing_country": {
                  "type": "string",
                  "nullable": true
                },
                "owner_kind": {
                  "type": "string",
                  "enum": [
                    "USER",
                    "BUSINESS",
                    "EXTERNAL"
                  ]
                },
                "vendor_data": {
                  "type": "string",
                  "nullable": true,
                  "description": "Votre identifiant pour l'utilisateur/l'entreprise propriétaire."
                },
                "owner_name": {
                  "type": "string",
                  "nullable": true
                },
                "institution_info": {
                  "type": "object"
                },
                "details": {
                  "type": "object",
                  "description": "Objet `payment_method` brut tel que soumis."
                },
                "external_owner_snapshot": {
                  "type": "object",
                  "nullable": true
                },
                "role": {
                  "type": "string",
                  "enum": [
                    "SOURCE",
                    "DESTINATION",
                    "FUNDING",
                    "BENEFICIARY"
                  ],
                  "description": "Manière dont cette méthode a été utilisée dans la transaction. L'endpoint de création attribue `SOURCE`/`DESTINATION` à partir de la direction (sortante : sujet = SOURCE ; entrante : sujet = DESTINATION)."
                }
              }
            },
            "description": "Moyens de paiement associés à la transaction."
          },
          "documents": {
            "type": "array",
            "description": "Fichiers joints à la transaction depuis la console. `[]` s'il n'y en a aucun.",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "label": {
                  "type": "string",
                  "nullable": true
                },
                "note": {
                  "type": "string",
                  "nullable": true
                },
                "uploaded_by": {
                  "type": "string",
                  "nullable": true
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "files": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "uuid": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "file_url": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true,
                        "description": "URL de téléchargement signée de courte durée ; récupérez-la en cas de besoin plutôt que de la stocker."
                      },
                      "original_filename": {
                        "type": "string",
                        "nullable": true
                      },
                      "file_size": {
                        "type": "integer",
                        "nullable": true
                      }
                    }
                  }
                }
              }
            }
          },
          "activities": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "activity_type": {
                  "type": "string",
                  "description": "Par ex. `TRANSACTION_CREATED`, `TRANSACTION_NOTE_ADDED`, `TRANSACTION_STATUS_CHANGED`."
                },
                "source": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "nullable": true
                },
                "title": {
                  "type": "string",
                  "nullable": true
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "metadata": {
                  "type": "object"
                },
                "occurred_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "description": "Entrées du journal d'activité (création, notes, examens manuels, changements de statut)."
          },
          "alerts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "severity": {
                  "type": "string",
                  "enum": [
                    "UNKNOWN",
                    "LOW",
                    "MEDIUM",
                    "HIGH",
                    "CRITICAL"
                  ]
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "OPEN",
                    "INVESTIGATING",
                    "AWAITING_USER",
                    "PENDING_SAR",
                    "SAR_FILED",
                    "RESOLVED",
                    "DISMISSED"
                  ]
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "RULE",
                    "PROVIDER",
                    "MANUAL"
                  ]
                },
                "metadata": {
                  "type": "object"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "due_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                }
              }
            },
            "description": "Toujours vide aujourd'hui. Une alerte ouverte est une transaction avec le statut `IN_REVIEW` ou `AWAITING_USER`."
          },
          "rule_runs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "rule": {
                  "type": "string",
                  "format": "uuid",
                  "description": "UUID de la règle exécutée."
                },
                "rule_title": {
                  "type": "string"
                },
                "rule_description": {
                  "type": "string",
                  "nullable": true
                },
                "rule_category": {
                  "type": "string"
                },
                "matched": {
                  "type": "boolean",
                  "description": "Indique si les conditions de la règle correspondaient à cette transaction. Une exécution n'est enregistrée que pour les règles correspondantes, de sorte que les évaluations en production portent toujours la valeur `true`."
                },
                "is_test": {
                  "type": "boolean",
                  "description": "Vrai lorsque la règle a été exécutée en mode TEST (aucun effet sur le statut/score)."
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "ACTIVE",
                    "DISABLED",
                    "TEST"
                  ]
                },
                "severity": {
                  "type": "string",
                  "nullable": true
                },
                "score_delta": {
                  "type": "integer",
                  "description": "Score ajouté par les actions `add_score` de cette règle."
                },
                "status_target": {
                  "type": "string",
                  "nullable": true,
                  "description": "Statut défini par une action `change_status`, le cas échéant."
                },
                "action_summary": {
                  "type": "string",
                  "nullable": true,
                  "description": "Résumé des actions exécutées par la règle, séparées par `; ` (par ex. `score +30; change_status:IN_REVIEW; add_tag:high_risk_country`). Parties : `score +N`, `change_status:<STATUS>`, `add_tag:<name>`, `add_note`, `add_to_list`, `open_case`. `null` lorsque la règle n'a exécuté aucune action."
                },
                "metadata": {
                  "type": "object",
                  "description": "Détail de l'évaluation : `scope_match`, `conditions[]` et `aggregations[]`. Chaque entrée de condition contient `field`, `operator`, `expected_value`, la `current_value` lue à partir de la transaction, `matched`, `group_index` et `group_logic`. Chaque entrée d'agrégation (vélocité / décompte / somme) contient `metric`, `field`, `operator`, `expected_value`, la `computed_value` obtenue par l'agrégat, `window`, `filters`, `matched` et `sample_references` ; les agrégations asynchrones différées ont `computed_value: null` et `deferred: true`. Un groupe de conditions imbriqué est une entrée `conditions[]` avec l'`operator` `any_of` ou `all_of`, `field` défini sur null, et les résultats de ses membres sous ses propres `conditions`."
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "description": "Résultats d'exécution par règle — quelle règle s'est déclenchée, avec quel impact sur le score."
          },
          "provider_results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "provider": {
                  "type": "string"
                },
                "result_type": {
                  "type": "string",
                  "enum": [
                    "FIAT_MONITORING",
                    "WALLET_SCREENING",
                    "TRANSACTION_SCREENING",
                    "TRAVEL_RULE",
                    "NETWORK_GRAPH",
                    "CUSTOM"
                  ]
                },
                "status": {
                  "type": "string"
                },
                "severity": {
                  "type": "string",
                  "nullable": true
                },
                "score": {
                  "type": "integer"
                },
                "summary": {
                  "type": "string",
                  "nullable": true
                },
                "payload": {
                  "type": "object",
                  "description": "Payload brut de la réponse du fournisseur."
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "description": "Payloads bruts des fournisseurs (filtrage AML, analyse blockchain, etc.)."
          },
          "travel_rule": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/TransactionTravelRule"
              }
            ],
            "description": "Transfert ou vérification Travel Rule. Renseigné lorsque `travel_rule_details` a été soumis, et également lorsque la Travel Rule est activée et que la transaction a été créée avec `transaction_category: travelRule` (Didit initie lui-même l'échange, même sans `travel_rule_details`). `null` lorsqu'aucun transfert ou vérification n'existe. Lors d'un transfert entrant, les champs `originator_data` et `beneficiary_data` de la contrepartie restent masqués (`data_masked: true`) jusqu'à ce que la détention du portefeuille soit confirmée."
          },
          "network_snapshot": {
            "type": "object",
            "nullable": true,
            "description": "Instantané du graphe des transactions/parties liées utilisé par le moteur de règles. Il s'agit soit du `network_snapshot` soumis avec la transaction, soit du graphe que Didit génère à partir d'un filtrage AML des portefeuilles réussi (qui remplace un graphe soumis). `null` si aucun des deux n'existe.",
            "properties": {
              "uuid": {
                "type": "string",
                "format": "uuid"
              },
              "nodes": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              },
              "edges": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              },
              "metrics": {
                "type": "object"
              }
            }
          },
          "remediation": {
            "type": "object",
            "nullable": true,
            "description": "Session de remédiation proposée à l'utilisateur lorsqu'une revérification est requise. Remplacée par `action_required`, qui est le bloc canonique ; conservée à des fins de rétrocompatibilité.",
            "properties": {
              "session_id": {
                "type": "string"
              },
              "session_token": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "format": "uri"
              },
              "status": {
                "type": "string"
              }
            }
          },
          "action_required": {
            "type": "object",
            "nullable": true,
            "description": "Action de l'utilisateur final en attente, requise pour terminer cette transaction, ou null lorsqu'il n'y en a aucune. Les SDK Didit lancent automatiquement l'action par défaut et actualisent la transaction lorsqu'elle se termine. Deux variantes, différenciées par `type` : `verification_session` (une session de vérification hébergée créée par une action de règle) et `wallet_ownership` (une session de widget de propriété de portefeuille générée automatiquement pour un transfert Travel Rule nécessitant une preuve de contrôle du portefeuille, conditionnée par le paramètre Travel Rule `auto_wallet_verification`). Lorsque les deux pourraient s'appliquer, `wallet_ownership` prévaut car elle bloque l'échange Travel Rule.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/TransactionVerificationSessionAction"
              },
              {
                "$ref": "#/components/schemas/TransactionWalletOwnershipAction"
              }
            ],
            "discriminator": {
              "propertyName": "type",
              "mapping": {
                "verification_session": "#/components/schemas/TransactionVerificationSessionAction",
                "wallet_ownership": "#/components/schemas/TransactionWalletOwnershipAction"
              }
            }
          },
          "cost_breakdown": {
            "type": "object",
            "nullable": true,
            "description": "Coût de cette transaction : `total_price` et `items`, un pour chaque frais facturé, chacun avec `usage_type`, `price`, `details` et `created_at`. Un nouveau filtrage de la même transaction constitue un nouvel élément."
          }
        }
      },
      "TravelRuleSettingsDetail": {
        "type": "object",
        "properties": {
          "is_enabled": {
            "type": "boolean",
            "description": "Indique si le flux géré de négociation Travel Rule est actif pour les transactions `travelRule` sortantes sur cette application."
          },
          "jurisdiction": {
            "type": "string",
            "maxLength": 8,
            "description": "Le code de juridiction d'exploitation de votre VASP. Par défaut `\"EU\"`. Didit l'associe au régime qu'il applique à vos transactions Travel Rule en tant que `travel_rule_regime` (par exemple, `EU` ou le code d'un membre de l'UE devient `eu`), sur lequel les règles de transaction peuvent s'appuyer. Les autres clients de Didit le voient comme votre juridiction dans l'annuaire des VASP une fois que le réseau Didit répertorie votre profil."
          },
          "name_matching_strictness": {
            "type": "string",
            "enum": [
              "NONE",
              "STRICT",
              "CONTAINS",
              "DEFAULT",
              "FUZZY"
            ],
            "description": "Niveau de rigueur requis pour la correspondance des noms de bénéficiaires avant qu'un transfert ne puisse passer à COMPLETED. `CONTAINS` accepte un nom dont tous les mots apparaissent dans l'autre."
          },
          "confirmation_timeout_hours": {
            "type": "integer",
            "minimum": 1,
            "description": "Nombre d'heures pendant lesquelles un transfert AWAITING_COUNTERPARTY peut rester non confirmé avant que le processus de nettoyage périodique ne le fasse expirer. Par défaut 48."
          },
          "timeout_outcome": {
            "type": "string",
            "enum": [
              "HOLD",
              "REJECT",
              "PROCEED"
            ],
            "description": "Ce qui advient de la transaction sous-jacente lorsqu'un transfert expire. Par défaut HOLD. sunrise_policy et non_responsive_policy prévalent lorsqu'elles s'appliquent et sont définies."
          },
          "threshold_amount": {
            "type": "string",
            "description": "Chaîne décimale, dans la devise par défaut de votre application. Montant de transfert minimal déclenchant un échange géré ; les transferts inférieurs à ce seuil sont résolus directement en NOT_APPLICABLE. Didit compare le montant de la transaction converti dans votre devise par défaut, ou l'`amount_in_default_currency` que vous envoyez ; lorsqu'aucun montant converti n'est disponible, le seuil ne s'applique pas. La valeur par défaut est \"0.00\" (le règlement européen TFR n'applique aucun montant minimal)."
          },
          "ownership_validation_mode": {
            "type": "string",
            "enum": [
              "FULL",
              "SIMPLIFIED",
              "AUTOMATED"
            ],
            "description": "Niveau de preuve requis pour la propriété d'un portefeuille. `FULL` requiert toujours une preuve (message signé, dépôt test ou capture d'écran examinée), jamais la simple déclaration de l'utilisateur final. `SIMPLIFIED` accepte une auto-déclaration en dessous de `simplified_validation_threshold` et une preuve au-dessus. `AUTOMATED` permet au carnet d'adresses et aux preuves antérieures de répondre d'eux-mêmes, auto-déclarations incluses tant que `allow_self_declaration` est true. Valeur par défaut `AUTOMATED`."
          },
          "simplified_validation_threshold": {
            "type": "string",
            "description": "Chaîne décimale, \"0.00\" par défaut. En mode `SIMPLIFIED`, un transfert inférieur à ce montant (dans la devise du seuil) accepte une auto-déclaration. Un transfert sans montant dans cette devise est considéré comme supérieur."
          },
          "data_sharing_fields": {
            "$ref": "#/components/schemas/TravelRuleDataSharingFields"
          },
          "matching_rules": {
            "$ref": "#/components/schemas/TravelRuleMatchingRules"
          },
          "legal_name": {
            "type": "string",
            "description": "Raison sociale de votre VASP. Requis (non vide) pour définir is_enabled sur true."
          },
          "lei": {
            "type": "string",
            "description": "Votre identifiant d'entité juridique (LEI), affiché dans le répertoire des VASP."
          },
          "compliance_email": {
            "type": "string",
            "format": "email",
            "description": "E-mail du contact de conformité pour votre profil VASP. Le réseau Didit ne répertorie votre profil qu'une fois cette adresse confirmée via un lien envoyé par e-mail (POST /v3/travel-rule/settings/compliance-email/confirmation/) ; la modifier nécessite une nouvelle confirmation."
          },
          "is_discoverable": {
            "type": "boolean",
            "description": "Indique si votre profil VASP peut être répertorié dans le réseau Didit : trouvable dans GET /v3/travel-rule/vasps/ par les autres clients de Didit et joignable sur le rail INTERNAL. Pour être répertorié, vous devez également disposer d'une application de production, activer la Travel Rule, renseigner une raison sociale et confirmer un e-mail de conformité ; didit_network indique les éléments manquants. Valeur par défaut : true."
          },
          "inbound_auto_accept": {
            "type": "boolean",
            "description": "Si true, une demande TRP entrante dont le portefeuille bénéficiaire correspond à une entrée vérifiée du carnet d'adresses avec un nom correspondant est approuvée automatiquement. Si false, cette demande reste en ON_HOLD jusqu'à ce que vous l'approuviez ou la refusiez via l'endpoint d'actionnariat. Les transferts sur le canal INTERNAL et postérieurs au dépôt ne sont pas affectés. Par défaut à true."
          },
          "allow_self_declaration": {
            "type": "boolean",
            "description": "Si true, le widget de propriété de portefeuille propose l'auto-déclaration comme méthode de preuve de repli. Par défaut à true."
          },
          "allow_screenshot_proof": {
            "type": "boolean",
            "description": "Si true, le widget de propriété de portefeuille propose le téléversement de capture d'écran comme méthode de preuve de propriété. Par défaut à true."
          },
          "auto_wallet_verification": {
            "type": "boolean",
            "description": "Si true, la soumission d'un transfert Travel Rule sortant nécessitant une preuve de contrôle du portefeuille par l'utilisateur final génère automatiquement une session de widget de propriété de portefeuille liée à la transaction et l'expose dans le bloc action_required de la transaction. Par défaut à true."
          },
          "vasp_attribution_enabled": {
            "type": "boolean",
            "description": "Si true, un transfert Travel Rule sortant qu'aucun canal ne peut acheminer est attribué grâce à l'analyse blockchain : le portefeuille de destination est résolu vers son VASP propriétaire, l'entité est enregistrée sur le transfert et dans le répertoire des VASP, et les canaux sont réévalués une fois avec le nom attribué. Par défaut à true."
          },
          "counterparty_screening_enabled": {
            "type": "boolean",
            "description": "Filtrage optionnel des sanctions et de la presse négative pour les VASP de contrepartie, facturé par filtrage au tarif du Filtrage AML d'entreprise. Lorsqu'il est activé, Didit filtre la contrepartie vers laquelle est effectué un échange sortant (en réutilisant un filtrage de moins de 30 jours) et vous pouvez en filtrer un avec POST /v3/travel-rule/vasps/{vasp_id}/screening/. Valeur par défaut false : rien n'est filtré ni facturé."
          },
          "sunrise_policy": {
            "type": "string",
            "enum": [
              "",
              "HOLD",
              "REJECT",
              "PROCEED"
            ],
            "description": "Action d'un transfert expiré sur sa transaction lorsque la contrepartie est une entrée de l'annuaire située dans une juridiction présente dans sunrise_jurisdictions, qui n'applique pas encore la Travel Rule : HOLD la passe en examen, REJECT la refuse, PROCEED laisse son statut inchangé. La valeur vide (par défaut) suit timeout_outcome. S'applique avant non_responsive_policy."
          },
          "sunrise_jurisdictions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "readOnly": true,
            "description": "Lecture seule. Les pays (ISO 3166 alpha-2) traités par Didit comme étant dans une période transitoire de la Travel Rule, où sunrise_policy s'applique. Actuellement CO, KH et VN. Toute autre juridiction, ainsi qu'une juridiction vide ou inconnue, suit timeout_outcome."
          },
          "non_responsive_policy": {
            "type": "string",
            "enum": [
              "",
              "HOLD",
              "REJECT",
              "PROCEED"
            ],
            "description": "Action d'un transfert expiré sur sa transaction lorsque la contrepartie est une entrée de l'annuaire dont la réactivité est UNRESPONSIVE : HOLD, REJECT ou PROCEED, comme pour timeout_outcome. La valeur vide (par défaut) suit timeout_outcome. sunrise_policy s'applique en premier lorsque les deux s'appliquent."
          },
          "travel_address": {
            "type": "string",
            "description": "Lecture seule. Travel Address propre à votre VASP - l'endpoint encodé de requête entrante TRP utilisé par les autres VASP pour vous joindre. Vide tant que `is_enabled` est faux."
          },
          "disabled_networks": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "GTR",
                "TRUST",
                "VERIFYVASP",
                "SYGNA"
              ]
            },
            "description": "Réseaux ayant renoncé à l'adhésion à la plateforme. Ne désactive pas vos propres adhésions connectées ni ne provisionne les réseaux indisponibles.",
            "default": []
          },
          "networks": {
            "type": "object",
            "readOnly": true,
            "description": "Par réseau, comment cette application enverrait et pourquoi elle ne le peut pas. Aucun réseau, y compris GTR, n'est inclus par défaut : un réseau est accessible via votre propre adhésion connectée, ou via l'adhésion de Didit une fois que l'adhésion de Didit à ce réseau est active et que votre propre participant y est actif. Il ne s'agit pas d'une vérification de l'état ou de la livraison en direct.",
            "properties": {
              "gtr": {
                "$ref": "#/components/schemas/TravelRuleNetworkState"
              },
              "trust": {
                "$ref": "#/components/schemas/TravelRuleNetworkState"
              },
              "verifyvasp": {
                "$ref": "#/components/schemas/TravelRuleNetworkState"
              },
              "sygna": {
                "$ref": "#/components/schemas/TravelRuleNetworkState"
              }
            }
          },
          "didit_network": {
            "type": "object",
            "readOnly": true,
            "description": "Indique si le réseau Didit répertorie votre profil VASP, afin que les autres clients de Didit le trouvent dans l'annuaire et le joignent via le canal INTERNAL, ainsi que chaque condition encore manquante.",
            "properties": {
              "listed": {
                "type": "boolean"
              },
              "missing": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "travel_rule_off",
                    "sandbox_application",
                    "not_discoverable",
                    "legal_name_missing",
                    "compliance_email_missing",
                    "compliance_email_unconfirmed",
                    "excluded_by_staff",
                    "internal_organization"
                  ]
                },
                "description": "Vide lorsqu'il est listé. compliance_email_unconfirmed : envoyez la confirmation avec POST /v3/travel-rule/settings/compliance-email/confirmation/ et ouvrez le lien reçu par e-mail. excluded_by_staff : Didit a marqué l'application comme étant un test, une démo ou une application interne."
              },
              "compliance_email_confirmed": {
                "type": "boolean",
                "description": "Indique si le compliance_email actuel a été confirmé via le lien envoyé par e-mail."
              }
            }
          }
        }
      },
      "TravelRuleSettingsUpdate": {
        "type": "object",
        "properties": {
          "is_enabled": {
            "type": "boolean"
          },
          "legal_name": {
            "type": "string",
            "maxLength": 255
          },
          "lei": {
            "type": "string",
            "maxLength": 20
          },
          "jurisdiction": {
            "type": "string",
            "maxLength": 8
          },
          "name_matching_strictness": {
            "type": "string",
            "enum": [
              "NONE",
              "STRICT",
              "CONTAINS",
              "DEFAULT",
              "FUZZY"
            ],
            "description": "`CONTAINS` accepte un nom dont tous les mots apparaissent dans l'autre."
          },
          "confirmation_timeout_hours": {
            "type": "integer",
            "minimum": 1
          },
          "timeout_outcome": {
            "type": "string",
            "enum": [
              "HOLD",
              "REJECT",
              "PROCEED"
            ]
          },
          "compliance_email": {
            "type": "string",
            "format": "email",
            "description": "E-mail du contact de conformité pour votre profil VASP. Le réseau Didit ne répertorie votre profil qu'une fois cette adresse confirmée via un lien envoyé par e-mail (POST /v3/travel-rule/settings/compliance-email/confirmation/) ; la modifier nécessite une nouvelle confirmation."
          },
          "is_discoverable": {
            "type": "boolean",
            "description": "Indique si votre profil VASP peut être répertorié dans le réseau Didit : trouvable dans GET /v3/travel-rule/vasps/ par les autres clients de Didit et joignable sur le rail INTERNAL. Pour être répertorié, vous devez également disposer d'une application de production, activer la Travel Rule, renseigner une raison sociale et confirmer un e-mail de conformité ; didit_network indique les éléments manquants. Valeur par défaut : true."
          },
          "threshold_amount": {
            "type": "string",
            "description": "Chaîne décimale, supérieure ou égale à zéro, dans la devise par défaut de votre application. Montant minimal du transfert déclenchant un échange géré."
          },
          "ownership_validation_mode": {
            "type": "string",
            "enum": [
              "FULL",
              "SIMPLIFIED",
              "AUTOMATED"
            ],
            "description": "Voir le champ de réponse du même nom."
          },
          "simplified_validation_threshold": {
            "type": "string",
            "description": "Chaîne décimale, supérieure ou égale à 0."
          },
          "data_sharing_fields": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleDataSharingFields"
              }
            ],
            "description": "Fusionné par type d'entité : un type d'entité que vous omettez conserve son choix actuel. Un choix qui ne peut pas respecter les obligations de donneur d'ordre de votre régime de `jurisdiction` (TFR de l'UE ou Recommandation 16 du GAFI), y compris une liste vide, est refusé avec `400`."
          },
          "matching_rules": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleMatchingRules"
              }
            ],
            "description": "Fusionné par type d'entité, et par champ au sein de celui-ci. Un champ que ce type d'entité ne compare pas (par exemple `date_of_birth` pour `company`) est refusé avec `400`."
          },
          "inbound_auto_accept": {
            "type": "boolean"
          },
          "allow_self_declaration": {
            "type": "boolean"
          },
          "allow_screenshot_proof": {
            "type": "boolean",
            "description": "Si true, le widget de propriété de portefeuille propose le téléversement de capture d'écran comme méthode de preuve de propriété. Par défaut à true."
          },
          "auto_wallet_verification": {
            "type": "boolean"
          },
          "vasp_attribution_enabled": {
            "type": "boolean"
          },
          "counterparty_screening_enabled": {
            "type": "boolean",
            "description": "Filtrage optionnel des sanctions et de la presse négative pour les VASP de contrepartie, facturé par filtrage au tarif du Filtrage AML d'entreprise. Lorsqu'il est activé, Didit filtre la contrepartie vers laquelle est effectué un échange sortant (en réutilisant un filtrage de moins de 30 jours) et vous pouvez en filtrer un avec POST /v3/travel-rule/vasps/{vasp_id}/screening/. Valeur par défaut false : rien n'est filtré ni facturé."
          },
          "sunrise_policy": {
            "type": "string",
            "enum": [
              "",
              "HOLD",
              "REJECT",
              "PROCEED"
            ],
            "description": "HOLD, REJECT, PROCEED, ou vide pour suivre timeout_outcome. Consultez le champ de réponse du même nom."
          },
          "non_responsive_policy": {
            "type": "string",
            "enum": [
              "",
              "HOLD",
              "REJECT",
              "PROCEED"
            ],
            "description": "HOLD, REJECT, PROCEED, ou vide pour suivre timeout_outcome. Consultez le champ de réponse du même nom."
          },
          "disabled_networks": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "GTR",
                "TRUST",
                "VERIFYVASP",
                "SYGNA"
              ]
            },
            "description": "Réseaux ayant renoncé à l'adhésion à la plateforme. Ne désactive pas vos propres adhésions connectées ni ne provisionne les réseaux indisponibles.",
            "default": []
          }
        },
        "description": "Tous les champs sont facultatifs ; PUT applique une mise à jour partielle."
      },
      "WalletAddressEntry": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "address": {
            "type": "string",
            "description": "L'adresse du portefeuille ; `\"\"` pour une entrée importée uniquement par son hash. Unique par application, chaîne et mémo, en comparant l'adresse sans tenir compte de la casse. Après avoir supprimé une entrée, vous pouvez enregistrer à nouveau la même adresse."
          },
          "chain": {
            "type": "string",
            "description": "Token de blockchain pour l'adresse, par exemple `ETH` ou `BTC`. Lorsque Didit achemine ou enregistre un transfert, il fait correspondre les entrées du carnet d'adresses sur l'adresse du portefeuille et, lorsque le transfert comporte une blockchain, sur cette valeur également, sans distinction de casse. La blockchain d'un transfert est `beneficiary_data.chain`, renseignée à partir de la blockchain crypto ou du symbole de devise de la transaction (par exemple `ETH`) si vous ne l'envoyez pas, ou à partir du `chain` d'un enregistrement après dépôt ; utilisez donc le même token partout. Une entrée avec une blockchain vide correspond à n'importe quelle blockchain. Un bénéficiaire Lightning (un identifiant de nœud ou une adresse Lightning) enregistré sur bitcoin est stocké en minuscules sur `LIGHTNING`, où les transferts Lightning sont mis en correspondance. Les blockchains connues sont stockées sous un identifiant canonique unique, quelle que soit l'orthographe envoyée : « ethereum », « Ethereum » et « ERC20 » sont toutes stockées sous ETH, « BNB Smart Chain » et « BEP20 » sous BNB, « tron » sous TRX. Un nom de blockchain inconnu est conservé tel quel."
          },
          "holder_vendor_data": {
            "type": "string",
            "description": "Votre identifiant interne pour le titulaire."
          },
          "holder_name": {
            "type": "string",
            "description": "Nom du titulaire du portefeuille, utilisé pour la correspondance du nom du bénéficiaire."
          },
          "entity_type": {
            "type": "string",
            "description": "Texte libre, valeur par défaut \"individual\"."
          },
          "is_ownership_verified": {
            "type": "boolean",
            "description": "Lecture seule. Indique si la propriété de cette adresse a été prouvée."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "travel_address": {
            "type": "string",
            "description": "La Travel Address du VASP de la contrepartie pour ce portefeuille, si elle est connue. Permet à Didit d'acheminer les transferts de ce bénéficiaire via le canal TRP, pour les actifs pris en charge par TRP (BTC, ETH et USDC sur un réseau désigné)."
          },
          "address_hash": {
            "type": "string",
            "description": "Lecture seule. SHA-256 de l'adresse en minuscules, au format hexadécimal en minuscules. Une entrée importée uniquement par son hachage est mise en correspondance sur cette valeur."
          },
          "memo": {
            "type": "string",
            "description": "Le tag de destination ou mémo faisant partie du portefeuille sur un réseau à mémo (XRP, XLM, EOS, ATOM, HBAR) ; `\"\"` pour l'adresse entière. Une entrée avec un mémo ne correspond qu'aux transferts mentionnant ce mémo ; une entrée sans mémo correspond à l'adresse entière."
          },
          "receiving_travel_address": {
            "type": "string",
            "readOnly": true,
            "description": "Votre Travel Address par portefeuille pour ce portefeuille : transmettez-la au VASP donneur d'ordre pour que sa demande TRP désigne ce portefeuille. Vide pour un portefeuille enregistré comme appartenant à un autre VASP, tant que Travel Rule est désactivé et avant l'enregistrement de votre profil VASP."
          }
        }
      },
      "WalletAddressEntryCreate": {
        "type": "object",
        "required": [
          "address"
        ],
        "properties": {
          "address": {
            "type": "string",
            "maxLength": 128,
            "description": "L'adresse du portefeuille. Une X-address XRP est stockée sous sa forme d'adresse classique et son tag, afin de correspondre aux transferts mentionnant l'une ou l'autre forme."
          },
          "chain": {
            "type": "string",
            "maxLength": 32,
            "description": "Token de la blockchain pour l'adresse, par exemple `ETH` ou `BTC`. Lorsque Didit achemine ou enregistre un transfert, il fait correspondre les entrées du carnet d'adresses sur l'adresse du portefeuille et, si le transfert comporte une blockchain, sur cette valeur également, sans tenir compte de la casse. La blockchain d'un transfert est `beneficiary_data.chain`, renseignée à partir de la blockchain crypto ou du symbole de devise de la transaction (par exemple `ETH`) si vous ne l'envoyez pas, ou à partir du `chain` d'un enregistrement après dépôt ; utilisez donc le même token partout. Une entrée avec une blockchain vide correspond à n'importe quelle blockchain. Les blockchains connues sont stockées sous un identifiant canonique unique, quelle que soit l'orthographe envoyée : \"ethereum\", \"Ethereum\" et \"ERC20\" sont toutes stockées sous forme d'ETH, \"BNB Smart Chain\" et \"BEP20\" sous forme de BNB, \"tron\" sous forme de TRX. Un nom de blockchain inconnu est conservé tel quel."
          },
          "holder_vendor_data": {
            "type": "string",
            "maxLength": 255
          },
          "holder_name": {
            "type": "string",
            "maxLength": 255
          },
          "entity_type": {
            "type": "string",
            "default": "individual",
            "maxLength": 16
          },
          "self_declared": {
            "type": "boolean",
            "default": false,
            "description": "En écriture seule. Lorsque la valeur est true, l'entrée est créée avec un actionnariat déjà vérifié via une preuve SELF_DECLARATION. Renvoie 400 lorsque `allow_self_declaration` est désactivé dans vos paramètres Travel Rule."
          },
          "travel_address": {
            "type": "string",
            "description": "Optionnel. La Travel Address du VASP de contrepartie pour ce portefeuille, activant le routage TRP pour les actifs pris en charge par TRP (BTC, ETH et USDC sur un réseau spécifié). Une Travel Address invalide renvoie 400.",
            "maxLength": 512
          },
          "memo": {
            "type": "string",
            "maxLength": 256,
            "description": "Facultatif. Le destination tag ou memo associé au portefeuille. XRP : un destination tag, un entier de 0 à 4294967295 (un nombre JSON est accepté). XLM : un memo texte jusqu'à 28 octets, un identifiant 64 bits ou un hachage de 32 octets en hexadécimal. EOS : jusqu'à 256 octets. ATOM : jusqu'à 256 caractères. HBAR : jusqu'à 100 octets. Les portefeuilles Bitcoin, EVM, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin et Lightning ne prennent aucun memo : en renseigner un renvoie une erreur `400`. Alias : `destinationTag` ou `destination_tag`."
          }
        }
      },
      "WalletAddressEntryUpdate": {
        "type": "object",
        "properties": {
          "holder_name": {
            "type": "string",
            "maxLength": 255
          },
          "holder_vendor_data": {
            "type": "string",
            "maxLength": 255
          },
          "entity_type": {
            "type": "string",
            "maxLength": 16
          },
          "travel_address": {
            "type": "string",
            "maxLength": 512
          }
        },
        "description": "PATCH est une mise à jour partielle ; la réponse ne renvoie que holder_name, holder_vendor_data, entity_type, travel_address, receiving_travel_address, label et owner_type."
      },
      "TravelRuleTransferDetail": {
        "type": "object",
        "description": "Objet de transfert complet renvoyé par les endpoints de confirmation d'actionnariat et de finalisation/annulation. Tant que l'actionnariat du portefeuille d'un transfert entrant n'est pas confirmé, les champs `originator_data` et `beneficiary_data` de la contrepartie sont renvoyés masqués (la première lettre de chaque mot est conservée ; le portefeuille, la blockchain et le routage VASP restent lisibles) et `data_masked` est à true.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "AWAITING_COUNTERPARTY",
              "ON_HOLD",
              "COMPLETED",
              "FINISHED",
              "CANCELLED",
              "EXPIRED",
              "COUNTERPARTY_MISMATCHED_DATA",
              "COUNTERPARTY_VASP_NOT_FOUND",
              "COUNTERPARTY_VASP_NOT_REACHABLE",
              "UNCONFIRMED_OWNERSHIP",
              "COUNTERPARTY_VASP_GENERAL_DECLINE",
              "NOT_ENOUGH_COUNTERPARTY_DATA",
              "NOT_APPLICABLE"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "INBOUND",
              "OUTBOUND"
            ]
          },
          "rail": {
            "type": "string",
            "nullable": true,
            "enum": [
              "INTERNAL",
              "TRP",
              "GTR",
              "TRUST",
              "VERIFYVASP",
              "SYGNA",
              "EMAIL",
              "TEST_VASP",
              null
            ],
            "description": "Le réseau sur lequel le transfert a été acheminé, ou null lorsqu'aucun réseau n'a été sélectionné (par exemple en dessous du seuil, un portefeuille de contrepartie auto-hébergé, un enregistrement après dépôt ou aucune contrepartie joignable). INTERNAL signifie que les deux parties sont des applications Didit ; EMAIL signifie que la contrepartie a été jointe via un lien de récupération envoyé par e-mail. TEST_VASP signifie que le VASP de test Didit a répondu au transfert sandbox. Sur GTR, VERIFYVASP et SYGNA, Didit lit la réponse de la contrepartie à partir de la réponse du réseau ou en l'interrogeant toutes les 5 minutes. TRUST effectue uniquement des envois, de sorte qu'un transfert TRUST reste à l'état AWAITING_COUNTERPARTY jusqu'à son expiration. Un canal de réseau n'est utilisé que si vous avez connecté votre propre adhésion à ce réseau. Il est choisi après le retour de la création de la transaction, il est donc null dans cette réponse."
          },
          "protocol": {
            "type": "string",
            "nullable": true
          },
          "ivms_version": {
            "type": "string",
            "example": "ivms101.2023"
          },
          "required": {
            "type": "boolean"
          },
          "ownership_confirmed": {
            "type": "boolean",
            "nullable": true
          },
          "deadline_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "timeline": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "string"
                },
                "at": {
                  "type": "string",
                  "format": "date-time"
                },
                "detail": {
                  "type": "string"
                },
                "name_match": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/TravelRuleNameMatch"
                    }
                  ],
                  "nullable": true,
                  "description": "La comparaison de noms déterminée par cette entrée, à côté de `detail`. Absente pour les entrées qui n'ont comparé aucun nom."
                },
                "reason": {
                  "type": "string",
                  "description": "Présent uniquement sur l'entrée d'une transition provoquée par un échec de livraison : `email_undeliverable` ou `delivery_failed`, la valeur indiquée par le `reason` du transfert."
                }
              }
            }
          },
          "counterparty_vasp": {
            "type": "object",
            "nullable": true,
            "properties": {
              "name": {
                "type": "string"
              },
              "lei": {
                "type": "string"
              },
              "dd_score": {
                "type": "integer",
                "description": "Score de due diligence de 0 à 100, où une valeur plus élevée est meilleure. Même échelle que dans l'annuaire des VASP."
              },
              "dd_score_breakdown": {
                "type": "object",
                "description": "Contributions par composant au dd_score, un objet par composant comme dans le répertoire VASP (jurisdiction, verification, protocol, lei, history, essentials, responsiveness), chacun comprenant {points, max, reason, detail}. {} jusqu'à ce que la contrepartie ait été évaluée.",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "points": {
                      "type": "number",
                      "description": "Points attribués pour ce composant."
                    },
                    "max": {
                      "type": "integer",
                      "description": "Nombre maximal de points que ce composant peut attribuer."
                    },
                    "reason": {
                      "type": "string",
                      "description": "Code lisible par machine du verdict du composant."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Raison lisible par l'utilisateur pour les points attribués."
                    }
                  }
                }
              },
              "dd_assessed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure de la dernière évaluation de diligence raisonnable. Null tant que la contrepartie n'a pas été évaluée."
              }
            }
          },
          "originator_data": {
            "type": "object",
            "description": "Partie du donneur d'ordre. Pour un transfert entrant, les valeurs de la contrepartie sont masquées jusqu'à ce que l'actionnariat soit confirmé."
          },
          "beneficiary_data": {
            "type": "object",
            "description": "Partie bénéficiaire. Pour un transfert entrant, les valeurs de la contrepartie sont masquées jusqu'à confirmation de la propriété."
          },
          "name_match": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleNameMatch"
              }
            ],
            "nullable": true,
            "description": "La comparaison de noms qui a déterminé le transfert, ou null tant qu'aucune n'a été exécutée. Lorsque les parties sont masquées, ainsi que sur la copie de l'autre client d'un échange INTERNAL, `transfer_name`, `compared_name`, `matched_names` et `mismatched_names` sont masqués. `score` et `matched` peuvent différer : `matched` suit le niveau d'exigence, `score` correspond à la similarité entre les deux noms complets."
          },
          "data_match": {
            "$ref": "#/components/schemas/TravelRuleDataMatch"
          },
          "mismatched_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Raccourci pour `data_match.mismatched_fields`. Vide lorsque rien ne diffère."
          },
          "data_unmasked": {
            "$ref": "#/components/schemas/TravelRuleDataUnmasked"
          },
          "data_masked": {
            "type": "boolean",
            "description": "Vrai tant que les données personnelles de la contrepartie sont masquées dans cette réponse."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "delivery": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleDelivery"
              }
            ],
            "description": "État d'acheminement du dernier message que ce transfert doit à l'autre partie. Vaut null lorsque le transfert n'a jamais dû en envoyer un (par exemple en dessous de `threshold_amount`, pour un portefeuille auto-hébergé déclaré ou un enregistrement sunrise)."
          },
          "discovery": {
            "type": "array",
            "description": "Manière dont Didit a recherché la contrepartie, une entrée par étape exécutée. Vide lorsqu'aucune recherche n'a été effectuée, par exemple lors d'un transfert entrant.",
            "items": {
              "$ref": "#/components/schemas/TravelRuleDiscoveryStep"
            }
          },
          "reason": {
            "type": "string",
            "description": "Raison pour laquelle un transfert `COUNTERPARTY_VASP_NOT_FOUND` ou `COUNTERPARTY_VASP_NOT_REACHABLE` est bloqué ; `\"\"` pour tout autre statut. Un échec de livraison la détermine en premier, sur `COUNTERPARTY_VASP_NOT_REACHABLE` uniquement : `email_undeliverable` (le fournisseur de messagerie a refusé l'e-mail de conformité et il ne reste aucune adresse à essayer : lors de son envoi, lors d'un rappel ou sous la forme d'un rejet permanent signalé ultérieurement) ou `delivery_failed` (le canal assurant la livraison a définitivement échoué : un canal réseau a refusé le message ou a épuisé ses tentatives, un hôte d'identité `TRP` n'a pas répondu, ou l'hôte `TRP` de la contrepartie n'a pas accepté la demande). Sinon, la trace `discovery` la détermine : `awaiting_end_user` (aucune étape n'a désigné de contrepartie que Didit peut joindre), `directory_match_no_route` (une étape a désigné un VASP de l'annuaire qui ne dispose d'aucun routage), `picked_member_without_proven_wallet` (l'utilisateur final a choisi un client Didit qui n'a pas prouvé le contrôle du portefeuille) ou `no_directory_match` lorsque la trace ne donne aucune autre raison. Un nouvel envoi fait progresser le transfert, ce qui efface le motif. Voir [Pourquoi un transfert est bloqué](/fr/transaction-monitoring/travel-rule#pourquoi-un-transfert-est-bloqué)."
          },
          "next_actions": {
            "type": "array",
            "description": "Ce qui permet de faire avancer le transfert ; `[]` pour tout statut autre que `COUNTERPARTY_VASP_NOT_FOUND` ou `COUNTERPARTY_VASP_NOT_REACHABLE`. `email_undeliverable` propose `update_compliance_email`, puis `resend`. `delivery_failed` propose `resend`. Un motif lié à la découverte propose `select_counterparty_vasp`, `declare_self_hosted`, `add_vasp_hint` et `resend`.",
            "items": {
              "$ref": "#/components/schemas/TravelRuleNextAction"
            }
          },
          "chain_details": {
            "$ref": "#/components/schemas/TravelRuleChainDetails"
          }
        }
      },
      "TravelRuleOwnershipConfirmRequest": {
        "type": "object",
        "required": [
          "confirmed"
        ],
        "properties": {
          "confirmed": {
            "type": "boolean",
            "description": "true pour confirmer la propriété, false pour la refuser."
          },
          "wallet_address": {
            "type": "string",
            "default": "",
            "description": "Transferts TRP entrants : l'adresse de paiement que Didit renvoie au VASP d'origine lorsque vous approuvez. Correspond par défaut à l'adresse de l'entrée correspondante du carnet d'adresses, puis à beneficiary_data.wallet_address. Sur un transfert vers un portefeuille auto-hébergé déclaré qui ne nomme aucun portefeuille de contrepartie, le portefeuille dont vous avez vérifié la propriété ; sans cela, la requête est rejetée avec une erreur 400. Ignoré pour les autres transferts."
          }
        }
      },
      "TravelRuleTransferPatchRequest": {
        "type": "object",
        "description": "Fournissez exactement un des éléments suivants : payment_txn_id (finish), action=cancel, action=resend, action=update_compliance_email avec compliance_email, action=update_originator_wallet avec wallet_address, ou action=beneficiary_vasp avec beneficiary_vasp.",
        "properties": {
          "payment_txn_id": {
            "type": "string",
            "description": "Le hash de la transaction on-chain. Nécessite que le transfert soit un transfert sortant au statut COMPLETED."
          },
          "action": {
            "type": "string",
            "enum": [
              "cancel",
              "resend",
              "update_compliance_email",
              "update_originator_wallet",
              "beneficiary_vasp"
            ],
            "description": "\"cancel\" annule un transfert non terminal. \"resend\" réexécute le routage pour un transfert sortant bloqué dans COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE ou NOT_ENOUGH_COUNTERPARTY_DATA. \"update_compliance_email\" remplace l'e-mail de conformité auquel la requête est envoyée, sur un transfert sortant dans l'un de ces trois statuts ; envoyez \"resend\" par la suite. \"update_originator_wallet\" enregistre le portefeuille depuis lequel les fonds sont réellement partis (`wallet_address`, `memo`). \"beneficiary_vasp\" vous permet d'indiquer vous-même le VASP de contrepartie (requiert `beneficiary_vasp`) pour un transfert sortant dans l'un de ces statuts : il est routé vers ce VASP et envoyé à nouveau."
          },
          "compliance_email": {
            "type": "string",
            "format": "email",
            "maxLength": 254,
            "description": "Requis avec `action: update_compliance_email`. Conservé comme `beneficiary_data.counterparty_vasp_email` de ce transfert : il appartient uniquement à ce transfert et n'est associé à aucune entrée d'annuaire ni à aucune liste de contacts."
          },
          "wallet_address": {
            "type": "string",
            "maxLength": 128,
            "description": "Avec `action: update_originator_wallet` : le portefeuille depuis lequel les fonds sont partis. Lorsque les entrées UTXO du transfert sont connues, il doit s'agir de l'une d'entre elles."
          },
          "memo": {
            "type": "string",
            "maxLength": 256,
            "description": "Avec `action: update_originator_wallet` : le mémo ou tag du portefeuille sur un réseau à mémos. Facultatif."
          },
          "beneficiary_vasp": {
            "type": "string",
            "format": "uuid",
            "description": "Requis avec action=beneficiary_vasp : l'`id` d'un VASP de l'annuaire, issu de `GET /v3/travel-rule/vasps/`. Votre choix prévaut sur chaque étape de découverte automatique, qui ne l'écrase jamais."
          }
        }
      },
      "VaspDirectoryEntry": {
        "type": "object",
        "description": "Un VASP de l'annuaire ou un membre du réseau Didit, avec les routes dont dispose votre application vers celui-ci. Un client n'est membre du réseau Didit que si son application est en production, que sa Travel Rule est activée, que son profil est visible, qu'il dispose d'une raison sociale et d'un e-mail de conformité confirmé, et que Didit n'a pas marqué l'application comme étant un test, une démo ou une application interne. Chaque ligne comporte également l'évaluation partagée de diligence raisonnable (dd_score, risk_level, responsiveness, essential_checks) ainsi que la propre décision de votre application, le filtrage de l'entité et les questionnaires, qu'aucun autre client ne voit.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "L'identifiant de l'entrée, pour GET /v3/travel-rule/vasps/{vasp_id}/."
          },
          "kind": {
            "type": "string",
            "enum": [
              "directory",
              "didit"
            ],
            "description": "directory pour une entrée de l'annuaire partagé ; didit pour un membre du réseau Didit."
          },
          "name": {
            "type": "string"
          },
          "lei": {
            "type": "string"
          },
          "jurisdiction": {
            "type": "string",
            "description": "Code pays ISO 3166, tel que fourni par la source."
          },
          "domains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Les domaines web du VASP. Toujours vide pour les membres du réseau Didit."
          },
          "reachable": {
            "type": "boolean",
            "description": "Indique si votre application dispose d'une route disponible vers ce VASP, ou vers l'une de ses entités pour une marque. Toujours true pour un membre du réseau Didit, sauf sur une application sandbox, où chaque ligne est false."
          },
          "aliases": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "trading_name",
                    "other_legal_name",
                    "network_name",
                    "attribution",
                    "merged",
                    "staff"
                  ],
                  "description": "trading_name, other_legal_name (issu du registre mondial LEI), network_name (le nom sur un réseau Travel Rule), attribution (le nom d'entité que l'analyse blockchain attribue aux portefeuilles du VASP), merged (le nom d'une entrée en double fusionnée dans celle-ci) ou staff."
                }
              }
            },
            "description": "Autres noms sous lesquels le VASP est identifié."
          },
          "networks": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Une inscription actuelle de ce VASP dans l'annuaire des membres d'un réseau Travel Rule. Une inscription TRISA indique qui est le VASP sur TRISA ; Didit ne dispose d'aucun canal TRISA, ce n'est donc jamais une route.",
              "properties": {
                "network": {
                  "type": "string",
                  "enum": [
                    "GTR",
                    "TRUST",
                    "VERIFYVASP",
                    "SYGNA",
                    "TRISA"
                  ]
                },
                "code": {
                  "type": "string",
                  "description": "L'identifiant du VASP sur ce réseau."
                },
                "listed_name": {
                  "type": "string",
                  "description": "Le nom sous lequel le réseau répertorie le VASP."
                },
                "country": {
                  "type": "string",
                  "description": "Le pays indiqué par le réseau, lorsqu'il en fournit un."
                },
                "verified_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true,
                  "description": "Date et heure auxquelles le personnel de Didit a vérifié la fiche. Null pour les fiches lues depuis un répertoire public."
                },
                "last_seen_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true,
                  "description": "Moment où la source a affiché l'inscription pour la dernière fois. Une inscription que la source n'a pas affichée pendant trois semaines est supprimée."
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "trisa_directory",
                    "staff"
                  ],
                  "description": "Origine de l'entrée : l'annuaire public TRISA ou le personnel Didit."
                }
              }
            }
          },
          "routes": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Un moyen par lequel votre application peut transmettre les données Travel Rule à ce VASP, dans l'ordre dans lequel l'envoi les tente. Un acheminement réseau nécessite une adhésion à ce réseau : la vôtre (connectée dans le Marketplace) ou celle de Didit dès lors que Didit en possède une. Sans elle, l'acheminement est indiqué comme non disponible avec le motif correspondant, jamais comme un moyen de joindre le VASP.",
              "properties": {
                "rail": {
                  "type": "string",
                  "enum": [
                    "INTERNAL",
                    "TRP",
                    "GTR",
                    "TRUST",
                    "VERIFYVASP",
                    "SYGNA",
                    "EMAIL"
                  ]
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "available",
                    "unavailable"
                  ]
                },
                "reason": {
                  "type": "string",
                  "enum": [
                    "",
                    "no_membership",
                    "network_switched_off",
                    "sandbox_application"
                  ],
                  "description": "Raison pour laquelle un itinéraire indisponible ne peut pas être utilisé : no_membership (ni vous ni Didit n'êtes membre de ce réseau), network_switched_off (vous avez désactivé ce réseau dans vos paramètres) ou sandbox_application (une application sandbox envoie uniquement au Test VASP de Didit, donc aucun itinéraire ne lui est accessible). Vide lorsque l'itinéraire est disponible."
                },
                "via": {
                  "type": "string",
                  "enum": [
                    "",
                    "own_membership",
                    "didit_membership",
                    "directory",
                    "contact",
                    "didit_network"
                  ],
                  "description": "Manière dont un itinéraire disponible est atteint : own_membership ou didit_membership pour un canal réseau, directory pour un endpoint TRP vérifié par l'annuaire, contact pour le canal EMAIL, didit_network pour un membre du réseau Didit. Vide lorsque l'itinéraire est indisponible."
                }
              }
            }
          },
          "umbrella": {
            "type": "object",
            "nullable": true,
            "description": "La marque dont cette entrée est une entité réglementée. Null lorsqu'elle ne fait pas partie d'une marque.",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "entities": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Une entité réglementée d'une marque : l'entité juridique qui reçoit un transfert.",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "lei": {
                  "type": "string"
                },
                "jurisdiction": {
                  "type": "string"
                },
                "reachable": {
                  "type": "boolean",
                  "description": "Indique si votre application dispose d'une route disponible vers celui-ci."
                }
              }
            },
            "description": "Pour une marque, les entités réglementées qui reçoivent ses transferts. Un transfert mentionnant la marque est dirigé vers l'entité joignable dans la juridiction indiquée (beneficiary_data.counterparty_vasp_jurisdiction), sinon vers l'entité liée au portefeuille de destination par attribution d'analyse blockchain, sinon vers l'unique entité joignable lorsqu'aucune juridiction n'est indiquée. Deux entités qui correspondent aussi bien l'une que l'autre ne sont jamais départagées au hasard."
          },
          "contacts": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Un contact de conformité auquel le canal EMAIL peut écrire.",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "email": {
                  "type": "string",
                  "format": "email"
                },
                "name": {
                  "type": "string"
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "staff",
                    "application",
                    "learned"
                  ],
                  "description": "staff : sélectionné par Didit ; application : ajouté par votre application ; learned : une adresse ayant répondu à une requête Travel Rule via son lien de réponse."
                },
                "scope": {
                  "type": "string",
                  "enum": [
                    "platform",
                    "application"
                  ],
                  "description": "Les contacts de la plateforme sont utilisés pour les transferts de chaque client de Didit ; les contacts de l'application sont privés pour votre application, qui ne voit que les siens."
                },
                "verified_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true,
                  "description": "Date et heure auxquelles quelqu'un à cette adresse a répondu à une requête. Null s'il n'y a pas encore eu de réponse."
                }
              }
            },
            "description": "Les contacts de la plateforme pour ce VASP ainsi que ceux de votre propre application."
          },
          "dd_status": {
            "type": "string",
            "enum": [
              "NOT_STARTED",
              "IN_PROGRESS",
              "COMPLETED",
              "REJECTED"
            ],
            "description": "Statut de vérification de l'entrée selon Didit, évalué par le composant de vérification de dd_score. Toujours COMPLETED pour un membre du réseau Didit."
          },
          "dd_score": {
            "type": "integer",
            "nullable": true,
            "minimum": 0,
            "maximum": 100,
            "description": "Le score de diligence raisonnable partagé d'une entrée de l'annuaire, de 0 à 100, où une valeur plus élevée est plus sûre (voir dd_score_semantic) : la somme des points dans dd_score_breakdown. Vaut null pour un membre du réseau Didit, qui n'est pas noté. Une entrée qui n'a pas encore été évaluée (dd_assessed_at valant null) affiche 0 avec un risk_level vide ; consultez donc risk_level plutôt que le score brut."
          },
          "reachable_rails": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "INTERNAL",
                "TRP",
                "GTR",
                "TRUST",
                "VERIFYVASP",
                "SYGNA",
                "EMAIL"
              ]
            },
            "description": "Canaux enregistrés sur l'entrée. Consultez les routes pour savoir ce que votre application peut utiliser aujourd'hui."
          },
          "is_didit_customer": {
            "type": "boolean",
            "description": "true pour un membre du réseau Didit (dd_status est toujours COMPLETED, dd_score est null et risk_level est vide pour ceux-ci) et pour une entrée de l'annuaire liée à un client Didit."
          },
          "dd_score_breakdown": {
            "type": "object",
            "description": "Un objet par composant de dd_score. Composants, leur poids (max) et leurs codes de motif : jurisdiction, 25 (jurisdiction_not_high_risk, jurisdiction_high_risk, jurisdiction_unknown) ; verification, 15 (dd_status_completed, dd_status_in_progress, dd_status_not_started, dd_status_rejected) ; protocol, 15 (native_rail, email_only, no_rail) ; lei, 10 (lei_valid, lei_missing) ; history, 10 (history, no_history) ; essentials, 15 (essential_checks, no_essential_checks) ; responsiveness, 10 (responsive, unresponsive, responsiveness_unknown). Vide pour un membre du réseau Didit.",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "points": {
                  "type": "number",
                  "description": "Points apportés par le composant, arrondis à une décimale."
                },
                "max": {
                  "type": "integer",
                  "description": "Le poids du composant : le maximum de points qu'il rapporte."
                },
                "reason": {
                  "type": "string",
                  "description": "Code lisible par machine du verdict du composant."
                },
                "detail": {
                  "type": "string",
                  "description": "Explication en anglais sur une ligne."
                }
              }
            }
          },
          "dd_assessed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles dd_score, risk_level et responsiveness ont été calculés pour la dernière fois : après qu'un échange avec l'entrée se termine, s'achève, expire, présente une non-concordance ou est refusé, lorsque Didit actualise ou traite l'entrée, et lors de l'actualisation hebdomadaire de l'annuaire. Null pour un membre du réseau Didit."
          },
          "dd_score_semantic": {
            "type": "string",
            "enum": [
              "higher_is_safer"
            ],
            "description": "Dans quel sens pointe dd_score : toujours higher_is_safer."
          },
          "risk_level": {
            "type": "string",
            "enum": [
              "LOW",
              "MEDIUM",
              "HIGH",
              ""
            ],
            "description": "La tranche dans laquelle se situe dd_score : LOW (70 ou plus), MEDIUM (40 à 69) ou HIGH (moins de 40). Vide pour un membre du réseau Didit et pour une entrée non encore évaluée. Filtrez dessus avec risk. Votre propre filtrage signalé ne modifie jamais cette valeur partagée : il passe plutôt counterparty_risk_level à HIGH dans vos règles."
          },
          "responsiveness": {
            "type": "object",
            "description": "Indique si le VASP répond aux requêtes Travel Rule : la part des requêtes initiées par les clients Didit à son intention au cours des 90 derniers jours auxquelles il a répondu. Seules les requêtes envoyées via un canal réseau ou protocolaire, ou par e-mail à une adresse partagée (l'adresse de conformité de l'entrée ou un contact de la plateforme), sont prises en compte ; une requête envoyée à une adresse saisie par un client ou au contact privé d'un client ne l'est jamais. Une requête expirée est considérée comme sans réponse ; un échange abouti, un refus ou une discordance de données constitue une réponse ; une requête annulée ou un canal inaccessible ne constituent ni l'un ni l'autre. Toujours UNKNOWN avec des compteurs à zéro pour un membre du réseau Didit.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "RESPONSIVE",
                  "UNRESPONSIVE",
                  "UNKNOWN"
                ],
                "description": "UNKNOWN avec moins de 5 requêtes ayant fait l'objet d'une décision sur la période ; UNRESPONSIVE lorsque moins de 10 pour cent d'entre elles ont reçu une réponse ; RESPONSIVE sinon."
              },
              "answered": {
                "type": "integer",
                "description": "Requêtes ayant fait l'objet d'une décision dans la fenêtre auxquelles le VASP a répondu."
              },
              "total": {
                "type": "integer",
                "description": "Requêtes ayant fait l'objet d'une décision dans la fenêtre : auxquelles il a été répondu, plus celles qui ont expiré."
              },
              "computed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "essential_checks": {
            "type": "object",
            "description": "Le rapport des vérifications essentielles d'une entrée de l'annuaire, généré uniquement à partir des sources vérifiées de la plateforme : immatriculation (un registre officiel répertorie le VASP : le registre intérimaire MiCA de l'UE, l'annuaire public TRISA ou le registre mondial des LEI), licence (une autorisation MiCA est enregistrée et en cours de validité), domaine (le domaine de l'entrée correspond à son endpoint TRP ou au site web indiqué par son registre) et LEI (son enregistrement LEI est actif, émis et conforme aux noms et au pays de l'entrée). La composante essentials de dd_score correspond à la proportion de vérifications évaluées qui ont réussi. Vide jusqu'à ce que l'actualisation hebdomadaire de l'annuaire vérifie l'entrée pour la première fois, et toujours vide pour un membre du réseau Didit.",
            "properties": {
              "level": {
                "type": "string",
                "enum": [
                  "essential"
                ]
              },
              "checked_at": {
                "type": "string",
                "format": "date-time"
              },
              "checks": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "enum": [
                        "registration",
                        "licence",
                        "domain",
                        "lei"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pass",
                        "fail",
                        "unknown"
                      ],
                      "description": "unknown lorsqu'aucune source enregistrée ne peut trancher la vérification."
                    },
                    "reason": {
                      "type": "string",
                      "description": "Code lisible par machine du verdict."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Explication en anglais sur une ligne."
                    }
                  }
                }
              },
              "passed": {
                "type": "integer"
              },
              "failed": {
                "type": "integer"
              },
              "unknown": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              }
            }
          },
          "decision": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleCounterpartyDecision"
              }
            ],
            "nullable": true,
            "description": "La décision de votre application sur ce VASP, ou pour une entité sans décision propre, celle de sa marque (inherited_from indique la marque). Null lorsqu'il n'y en a aucune. Privée pour votre application."
          },
          "entity_screening": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleCounterpartyScreening"
              }
            ],
            "nullable": true,
            "description": "Le dernier filtrage des sanctions et de presse négative réalisé par votre application pour ce VASP. Null si vous ne l'avez jamais filtré. Privé pour votre application."
          },
          "questionnaires": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TravelRuleCounterpartyQuestionnaire"
            },
            "description": "Les questionnaires de due diligence de votre application avec ce VASP, du plus récent au plus ancien. Privés pour votre application."
          }
        },
        "example": {
          "id": "0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91",
          "kind": "directory",
          "name": "Example Counterparty VASP",
          "lei": "529900EXAMPLECPTY001",
          "jurisdiction": "DE",
          "domains": [
            "counterparty.example"
          ],
          "reachable": true,
          "aliases": [
            {
              "name": "Example Counterparty",
              "kind": "trading_name"
            }
          ],
          "networks": [
            {
              "network": "GTR",
              "code": "EXAMPLE01",
              "listed_name": "Example Counterparty VASP",
              "country": "DE",
              "verified_at": "2026-10-12T09:30:00Z",
              "last_seen_at": "2026-10-12T09:30:00Z",
              "source": "staff"
            }
          ],
          "routes": [
            {
              "rail": "GTR",
              "status": "unavailable",
              "reason": "no_membership",
              "via": ""
            },
            {
              "rail": "EMAIL",
              "status": "available",
              "reason": "",
              "via": "contact"
            }
          ],
          "umbrella": null,
          "entities": [],
          "contacts": [
            {
              "id": "6c1f9b8e-2d4a-4f7e-8b3c-5a9d0e1f2a3b",
              "email": "travelrule@counterparty.example",
              "name": "Travel Rule desk",
              "source": "staff",
              "scope": "platform",
              "verified_at": null
            }
          ],
          "dd_status": "NOT_STARTED",
          "dd_score": 62,
          "dd_score_breakdown": {
            "jurisdiction": {
              "points": 25.0,
              "max": 25,
              "reason": "jurisdiction_not_high_risk",
              "detail": "DEU is not on the high-risk jurisdiction list"
            },
            "verification": {
              "points": 3.8,
              "max": 15,
              "reason": "dd_status_not_started",
              "detail": "due diligence status NOT_STARTED"
            },
            "protocol": {
              "points": 6.0,
              "max": 15,
              "reason": "email_only",
              "detail": "reachable over the email fallback only"
            },
            "lei": {
              "points": 10.0,
              "max": 10,
              "reason": "lei_valid",
              "detail": "valid LEI on record"
            },
            "history": {
              "points": 5.0,
              "max": 10,
              "reason": "no_history",
              "detail": "no exchange history"
            },
            "essentials": {
              "points": 7.5,
              "max": 15,
              "reason": "no_essential_checks",
              "detail": "no decided essential check yet"
            },
            "responsiveness": {
              "points": 5.0,
              "max": 10,
              "reason": "responsiveness_unknown",
              "detail": "0 decided recent requests, too few to judge"
            }
          },
          "dd_assessed_at": "2026-10-12T09:30:00Z",
          "dd_score_semantic": "higher_is_safer",
          "risk_level": "MEDIUM",
          "responsiveness": {
            "status": "UNKNOWN",
            "answered": 0,
            "total": 0,
            "computed_at": "2026-10-12T09:30:00Z"
          },
          "essential_checks": {},
          "reachable_rails": [
            "GTR",
            "EMAIL"
          ],
          "is_didit_customer": false,
          "decision": {
            "decision": "APPROVED",
            "reason": "Licensed in DE, questionnaire reviewed",
            "decided_by": "",
            "updated_at": "2026-10-14T10:05:00Z",
            "inherited_from": null
          },
          "entity_screening": {
            "id": "7a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
            "status": "Approved",
            "total_hits": 0,
            "score": null,
            "screened_at": "2026-10-14T09:58:00Z",
            "fresh": true,
            "flagged": false
          },
          "questionnaires": [
            {
              "id": "8b7a6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
              "status": "ANSWERED",
              "form_version": "1",
              "sent_to": "travelrule@counterparty.example",
              "sent_at": "2026-09-02T08:00:00Z",
              "expires_at": "2026-10-02T08:00:00Z",
              "answered_at": "2026-09-04T15:20:00Z",
              "valid_until": "2027-09-04T15:20:00Z",
              "current": true,
              "answers": {
                "legal_name": "Example Counterparty VASP, incorporated in the example jurisdiction.",
                "licensing": "Crypto-asset service provider authorised under MiCA by its national regulator, licence active.",
                "jurisdictions": "EU and EEA. We do not serve the United States.",
                "aml_program": "Written AML/CFT policy, annual independent review, last completed in March 2026.",
                "compliance_officer": "Head of Compliance, reachable at compliance@counterparty.example.",
                "sanctions_screening": "Customers at onboarding and daily; counterparties on every transfer.",
                "transaction_monitoring": "Rule-based monitoring with analyst review; suspicious activity reports filed with the FIU.",
                "travel_rule": "TRP and email; we answer requests within one business day.",
                "custody": "Segregated customer wallets held with a qualified custodian, insured.",
                "ownership": "No shareholder holds 25 percent or more; parent company Example Holding Group.",
                "record_keeping": "Five-year record-keeping for Travel Rule and transaction data, as our regulator requires.",
                "data_protection": "Encrypted at rest and in transit, stored in the EU."
              }
            }
          ]
        }
      },
      "TravelRuleCounterpartyDecision": {
        "type": "object",
        "description": "La décision de votre application sur un VASP de la contrepartie. Privée pour votre application : elle ne modifie jamais l'entrée partagée de l'annuaire et aucun autre client ne la voit. Elle agit uniquement à travers vos règles de transaction (le champ de règle counterparty_dd_status et les préconfigurations travel-rule-counterparty-blocked et travel-rule-counterparty-restricted) ; elle ne modifie jamais la manière dont un transfert est acheminé.",
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "APPROVED",
              "RESTRICTED",
              "BLOCKED"
            ],
            "description": "APPROVED : votre équipe a validé la contrepartie. RESTRICTED : les transferts vers celle-ci peuvent être effectués après examen. BLOCKED : votre équipe l'a refusée."
          },
          "reason": {
            "type": "string",
            "maxLength": 255,
            "description": "Motif en texte libre que vous avez indiqué, vide s'il n'y en a aucun."
          },
          "decided_by": {
            "type": "string",
            "description": "L'utilisateur de la console qui a pris ou modifié pour la dernière fois la décision. Vide lorsqu'une clé API l'a prise."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "inherited_from": {
            "type": "object",
            "nullable": true,
            "description": "La marque dont cette entité suit la décision parce que vous n'en avez pris aucune sur l'entité elle-même. Null lorsque la décision est propre à la contrepartie.",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              }
            }
          }
        }
      },
      "TravelRuleCounterpartyDecisionResponse": {
        "type": "object",
        "properties": {
          "decision": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleCounterpartyDecision"
              }
            ],
            "nullable": true,
            "description": "La décision qui s'applique à la contrepartie pour votre application : la sienne, sinon (pour une entité d'une marque) celle de la marque. Null lorsqu'il n'y en a aucune."
          }
        }
      },
      "TravelRuleCounterpartyDecisionRequest": {
        "type": "object",
        "required": [
          "decision"
        ],
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "APPROVED",
              "RESTRICTED",
              "BLOCKED"
            ]
          },
          "reason": {
            "type": "string",
            "maxLength": 255,
            "description": "Optionnel. Remplace le motif précédent ; omettez-le pour l'effacer."
          }
        }
      },
      "TravelRuleCounterpartyScreening": {
        "type": "object",
        "description": "Un filtrage des sanctions et de la presse négative de l'entité contrepartie, exécuté pour votre application et facturé à celle-ci. Réservé à votre application : un autre client ne le verra jamais.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "Approved",
              "In Review",
              "Declined"
            ],
            "description": "Approuvé : aucune correspondance possible ne nécessite d'attention. En cours d'examen ou refusé : une correspondance possible avec des sanctions ou de la presse négative."
          },
          "total_hits": {
            "type": "integer",
            "description": "Nombre de correspondances possibles renvoyées par le filtrage."
          },
          "score": {
            "type": "number",
            "nullable": true,
            "description": "Le score de risque le plus élevé parmi les correspondances possibles. Null si rien ne correspondait."
          },
          "screened_at": {
            "type": "string",
            "format": "date-time"
          },
          "fresh": {
            "type": "boolean",
            "description": "Indique si le filtrage est plus récent que fresh_days (30 jours). Un filtrage récent est réutilisé au lieu d'être à nouveau facturé."
          },
          "flagged": {
            "type": "boolean",
            "description": "true tant que le filtrage est récent et que son statut est In Review ou Declined. Tant que votre dernier filtrage est signalé et que le filtrage de la contrepartie reste activé, counterparty_risk_level est HIGH dans vos règles."
          }
        }
      },
      "TravelRuleCounterpartyScreeningStatus": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Votre paramètre Travel Rule counterparty_screening_enabled. Désactivé par défaut ; rien n'est filtré ni facturé tant qu'il est désactivé."
          },
          "price": {
            "type": "string",
            "description": "Chaîne décimale, en USD : coût d'un filtrage pour votre organisation, le prix du Filtrage AML d'entreprise."
          },
          "fresh_days": {
            "type": "integer",
            "description": "Nombre de jours pendant lesquels un filtrage reste valide et est réutilisé."
          },
          "screening": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleCounterpartyScreening"
              }
            ],
            "nullable": true,
            "description": "Votre dernier filtrage de la contrepartie. Vaut null si vous ne l'avez jamais filtrée."
          }
        }
      },
      "TravelRuleCounterpartyScreeningRequest": {
        "type": "object",
        "properties": {
          "refresh": {
            "type": "boolean",
            "default": false,
            "description": "true filtre à nouveau (et facture à nouveau) même lorsqu'un filtrage récent existe."
          }
        }
      },
      "TravelRuleCounterpartyScreeningResult": {
        "type": "object",
        "properties": {
          "outcome": {
            "type": "string",
            "enum": [
              "screened",
              "reused"
            ],
            "description": "screened : un nouveau filtrage a été exécuté et facturé (201). reused : un filtrage récent a été renvoyé et rien n'a été facturé (200)."
          },
          "screening": {
            "$ref": "#/components/schemas/TravelRuleCounterpartyScreening"
          }
        }
      },
      "TravelRuleCounterpartyQuestionnaire": {
        "type": "object",
        "description": "Un questionnaire de vigilance envoyé par votre application à la contrepartie : le questionnaire standard de Didit, envoyé par e-mail à une adresse de conformité enregistrée avec un lien de réponse à usage unique. Réservé à votre application.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "SENT",
              "ANSWERED",
              "EXPIRED"
            ],
            "description": "SENT : en attente de réponses. ANSWERED : la contrepartie a répondu à toutes les questions. EXPIRED : le lien de réponse s'est fermé sans réponse (son délai a expiré ou un questionnaire plus récent l'a remplacé), ou les réponses ont dépassé valid_until."
          },
          "form_version": {
            "type": "string",
            "description": "Version du questionnaire standard de Didit à laquelle les réponses appartiennent. Actuellement 1."
          },
          "sent_to": {
            "type": "string",
            "format": "email"
          },
          "sent_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "La date limite de réponse, 30 jours après l'envoi. Le lien cesse de fonctionner après cette échéance."
          },
          "answered_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "valid_until": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Durée pendant laquelle les réponses restent valides : 365 jours après avoir répondu. Null tant qu'aucune réponse n'a été apportée."
          },
          "current": {
            "type": "boolean",
            "description": "true tant que le questionnaire est ANSWERED et que valid_until n'est pas dépassé."
          },
          "answers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Les réponses indexées par l'ID de question : legal_name, licensing, jurisdictions, aml_program, compliance_officer, sanctions_screening, transaction_monitoring, travel_rule, custody, ownership, record_keeping, data_protection. Chaque réponse contient jusqu'à 2 000 caractères. Les réponses sont vides jusqu'à ce qu'une réponse soit apportée."
          }
        }
      },
      "TravelRuleCounterpartyQuestionnaireRequest": {
        "type": "object",
        "properties": {
          "sent_to": {
            "type": "string",
            "format": "email",
            "description": "Optionnel. Une adresse de conformité enregistrée pour la contrepartie : pour une entrée d'annuaire, son adresse de conformité ou un contact visible par votre application ; pour un membre du réseau Didit, son e-mail de conformité confirmé. Par défaut : l'adresse à laquelle un e-mail Travel Rule destiné à la contrepartie est envoyé (votre propre contact en premier, puis un contact de la plateforme, puis l'adresse de conformité de l'entrée)."
          }
        }
      },
      "TravelRuleCounterpartyQuestionnaireList": {
        "type": "object",
        "properties": {
          "questionnaires": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TravelRuleCounterpartyQuestionnaire"
            },
            "description": "Les plus récents en premier."
          }
        }
      },
      "TravelRulePickupInfo": {
        "type": "object",
        "description": "L'échange en attente derrière un lien de récupération envoyé par e-mail, tel que l'affiche la page de réponse de la contrepartie.",
        "properties": {
          "reference": {
            "type": "string",
            "format": "uuid",
            "description": "L'UUID du transfert, tel qu'il apparaît dans la console du VASP émetteur."
          },
          "requested_at": {
            "type": "string",
            "format": "date-time"
          },
          "originator_vasp_name": {
            "type": "string"
          },
          "originator_vasp_lei": {
            "type": "string"
          },
          "recipient_vasp_name": {
            "type": "string",
            "description": "Le VASP de la contrepartie auquel la requête est adressée."
          },
          "language": {
            "type": "string",
            "description": "La langue de l'e-mail de demande et de la page de réponse, provenant de la juridiction de la contrepartie."
          },
          "amount": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "fiat_amount": {
            "type": "string",
            "description": "La valeur convertie fournie par l'expéditeur, ou vide."
          },
          "fiat_currency": {
            "type": "string"
          },
          "chain": {
            "type": "string"
          },
          "beneficiary_wallet": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "ivms_version": {
            "type": "string"
          },
          "deadline_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où le lien cesse de répondre."
          },
          "reminders_sent": {
            "type": "integer"
          },
          "contact": {
            "type": "string",
            "description": "La valeur `?contact=` du lien, renvoyée en écho ; vide lorsque le lien n'en comporte pas."
          },
          "decline_reasons": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "data_mismatch",
                "not_our_customer",
                "wallet_not_hosted",
                "sanctions",
                "risk_appetite",
                "jurisdiction",
                "insufficient_data",
                "other"
              ]
            },
            "description": "Les valeurs acceptées par `decline_reason`."
          },
          "join_invitation": {
            "type": "object",
            "description": "Indique si la contrepartie dispose d'une invitation active pour rejoindre Didit gratuitement. Le lien d'invitation est transmis uniquement par e-mail à l'adresse invitée, donc `url` est vide ici.",
            "properties": {
              "eligible": {
                "type": "boolean"
              },
              "url": {
                "type": "string"
              }
            }
          },
          "originator_data": {
            "type": "object",
            "description": "Les champs du donneur d'ordre que le VASP émetteur partage (`data_sharing_fields`). Le nom et le portefeuille sont toujours inclus."
          },
          "beneficiary_data": {
            "type": "object"
          },
          "ivms_request": {
            "type": "object",
            "description": "La même requête sous la forme d'un objet IVMS 101. Omis tant que `data_masked` est à true."
          },
          "data_masked": {
            "type": "boolean",
            "description": "Toujours false sur cet endpoint : une requête d'e-mail est sortante, et le propre utilisateur de l'expéditeur n'est jamais masqué."
          }
        }
      },
      "TravelRulePickupRespondRequest": {
        "type": "object",
        "required": [
          "decision"
        ],
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "accept",
              "decline"
            ]
          },
          "beneficiary_name": {
            "type": "string",
            "description": "Le nom du bénéficiaire tel qu'il figure dans vos dossiers, soumis à la règle de nom du VASP donneur d'ordre. `ivms_response` prévaut lorsqu'il nomme le bénéficiaire.",
            "maxLength": 255
          },
          "decline_reason": {
            "type": "string",
            "enum": [
              "",
              "data_mismatch",
              "not_our_customer",
              "wallet_not_hosted",
              "sanctions",
              "risk_appetite",
              "jurisdiction",
              "insufficient_data",
              "other"
            ],
            "description": "Raison de votre refus. Enregistrée sur la chronologie du transfert du VASP donneur d'ordre. Vide (par défaut) lorsque vous ne donnez aucun motif."
          },
          "decline_detail": {
            "type": "string",
            "maxLength": 512,
            "description": "Texte libre ; requis lorsque `decision` vaut `decline` et `decline_reason` vaut `other`."
          },
          "ivms_response": {
            "type": "object",
            "description": "Votre réponse IVMS 101 complète. Son nom de bénéficiaire prévaut sur `beneficiary_name`."
          },
          "contact": {
            "type": "string",
            "format": "uuid",
            "description": "Le contact auquel le lien a été envoyé, à partir de la valeur `?contact=` du lien. Lorsque le corps l'omet, le paramètre de requête `contact` est utilisé."
          }
        }
      },
      "TravelRuleInboundRequest": {
        "type": "object",
        "required": [
          "chain",
          "txid",
          "wallet_address",
          "amount",
          "currency"
        ],
        "properties": {
          "chain": {
            "type": "string",
            "description": "Blockchain sur laquelle le dépôt a été réglé, par exemple `ETH`. Stocké en minuscules et comparé sans distinction de casse avec les entrées de votre carnet d'adresses de portefeuilles, utilisez donc le même token de blockchain ici.",
            "maxLength": 32
          },
          "txid": {
            "type": "string",
            "description": "Hash de transaction on-chain. Dédupliqué avec wallet_address.",
            "maxLength": 128
          },
          "wallet_address": {
            "type": "string",
            "description": "Le portefeuille de destination sur lequel vous avez reçu le dépôt. Une adresse X XRP est séparée en son adresse classique et son tag.",
            "maxLength": 128
          },
          "amount": {
            "type": "string",
            "description": "Montant du dépôt sous forme de chaîne décimale, supérieur ou égal à zéro, avec jusqu'à 18 décimales."
          },
          "currency": {
            "type": "string",
            "description": "Actif de dépôt, par ex. « USDC ».",
            "maxLength": 16
          },
          "originator_data": {
            "type": "object",
            "description": "Informations sur le donneur d'ordre transmises par le VASP émetteur, si elles sont connues, sous forme d'objet plat tel que `{\"name\": \"...\"}`. Didit y lit name (ou full_name), first_name, last_name et vendor_data.",
            "additionalProperties": true
          },
          "beneficiary_data": {
            "type": "object",
            "description": "Détails du bénéficiaire (votre client), sous la forme d'un objet plat tel que `{\"name\": \"...\"}`. Didit compare le nom avec le holder_name de l'entrée correspondante du carnet d'adresses, et définit wallet_address et chain à partir de la requête.",
            "additionalProperties": true
          },
          "originating_vasp": {
            "type": "object",
            "description": "Description optionnelle du VASP expéditeur. Elle reste uniquement associée à ce transfert (`metadata.originating_vasp`, ainsi que le VASP donneur d'ordre du transfert dans GET /v3/travel-rule/transfers/) ; elle ne crée, ne modifie ni ne lie jamais une entrée de l'annuaire partagé des VASP.",
            "properties": {
              "name": {
                "type": "string",
                "maxLength": 255
              },
              "lei": {
                "type": "string",
                "maxLength": 20,
                "description": "Optionnel. Un LEI ISO 17442 valide de 20 caractères, ou vide."
              },
              "travel_address": {
                "type": "string",
                "description": "La Travel Address de l'expéditeur, enregistrée sur ce transfert.",
                "maxLength": 512
              }
            }
          },
          "memo": {
            "type": "string",
            "maxLength": 256,
            "description": "Optionnel. Le tag de destination ou memo du dépôt sur un réseau à memo : sur une adresse de dépôt partagée, c'est ce qui distingue vos clients, et l'entrée du carnet d'adresses correspondant à ce memo est mise en correspondance. XRP : un tag de destination, un nombre entier de 0 à 4294967295 (un nombre JSON est accepté). XLM : un memo textuel jusqu'à 28 octets, un identifiant 64 bits ou un hachage de 32 octets en hexadécimal. EOS : jusqu'à 256 octets. ATOM : jusqu'à 256 caractères. HBAR : jusqu'à 100 octets. Les portefeuilles Bitcoin, EVM, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin et Lightning n'acceptent aucun memo : en indiquer un renvoie un `400`. Alias : `destinationTag` ou `destination_tag`."
          },
          "utxo": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleUtxo"
              }
            ],
            "description": "Optionnel, blockchains UTXO uniquement. Les entrées et sorties de la transaction de dépôt : le portefeuille de l'expéditeur est le `originator_data.wallet_address` déclaré, sinon l'entrée la plus importante."
          }
        }
      },
      "TravelRuleInboundResponse": {
        "type": "object",
        "properties": {
          "transaction_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID de transaction Didit pour le dépôt entrant."
          },
          "txn_id": {
            "type": "string",
            "description": "txn_id de la transaction entrante : généré par Didit lorsque Didit a créé la transaction, ou le vôtre lorsqu'un dépôt non réclamé a été réutilisé."
          },
          "created": {
            "type": "boolean",
            "description": "true lorsque cet appel a enregistré le transfert (HTTP 201) ; false lorsqu'un transfert pour le même txid et la même wallet_address existait déjà (HTTP 200)."
          },
          "travel_rule": {
            "$ref": "#/components/schemas/TravelRuleTransferDetail"
          }
        }
      },
      "TravelRuleTestVaspInboundRequest": {
        "type": "object",
        "required": [
          "beneficiary_wallet_address"
        ],
        "properties": {
          "beneficiary_wallet_address": {
            "type": "string",
            "description": "L'adresse du portefeuille de destination. Le VASP de test Didit envoie vers celle-ci, mise en correspondance avec le carnet d'adresses de votre portefeuille sur la blockchain de l'actif. Un portefeuille sans entrée correspondante est accepté et la transaction entrante est enregistrée sous le statut ON_HOLD."
          },
          "scenario": {
            "type": "string",
            "enum": [
              "accept",
              "name_mismatch"
            ],
            "default": "accept",
            "description": "Ce que le Didit Test VASP déclare pour le bénéficiaire. `accept` indique le nom du titulaire lui-même ; `name_mismatch` indique un nom auquel aucun titulaire ne souscrit. La décision elle-même vous appartient toujours."
          },
          "chain": {
            "type": "string",
            "default": "ETH",
            "description": "Blockchain de l'actif."
          },
          "amount": {
            "type": "string",
            "default": "1",
            "description": "Montant sous forme de chaîne décimale."
          },
          "currency": {
            "type": "string",
            "default": "ETH",
            "description": "Code de l'actif."
          },
          "reference": {
            "type": "string",
            "description": "Clé d'idempotence optionnelle. Une répétition avec la même valeur renvoie le transfert réservé par le premier appel."
          }
        }
      },
      "TravelRuleTestVaspInboundResponse": {
        "type": "object",
        "properties": {
          "transaction_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID de transaction Didit du virement entrant."
          },
          "txn_id": {
            "type": "string",
            "description": "txn_id généré par Didit."
          },
          "scenario": {
            "type": "string",
            "description": "Le scénario qui a été exécuté."
          },
          "travel_rule_status": {
            "type": "string",
            "description": "Le statut auquel la propre décision de votre application a abouti."
          },
          "detail": {
            "type": "string",
            "description": "Raison pour laquelle le transfert s'est résolu avec ce statut."
          },
          "test_vasp": {
            "type": "boolean",
            "description": "Toujours true : l'expéditeur était le Didit Test VASP."
          },
          "travel_rule": {
            "$ref": "#/components/schemas/TravelRuleTransferDetail"
          }
        }
      },
      "TravelRuleWidgetSessionCreate": {
        "type": "object",
        "properties": {
          "wallet_address": {
            "type": "string",
            "description": "L'adresse du portefeuille à vérifier. Optionnelle ; si elle n'est pas renseignée, l'adresse doit être fournie lorsqu'une preuve est démarrée.",
            "maxLength": 128
          },
          "chain": {
            "type": "string",
            "description": "Token de la blockchain pour l'adresse, par exemple `ETH`, `BTC` ou `SOL`. Utilisez le même token que dans votre carnet d'adresses de portefeuilles. La signature de message et le test Satoshi ne sont proposés que pour une blockchain prise en charge. L'entrée du carnet d'adresses vérifiée par la preuve la stocke sous son identifiant canonique (ETH, BTC, SOL, TRX).",
            "maxLength": 32
          },
          "holder_name": {
            "type": "string",
            "description": "Nom du titulaire du portefeuille, utilisé pour la correspondance du nom du bénéficiaire.",
            "maxLength": 255
          },
          "vendor_data": {
            "type": "string",
            "description": "Votre identifiant interne pour le titulaire, reporté sur l'entrée créée dans le carnet d'adresses.",
            "maxLength": 255
          },
          "transaction_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optionnel. UUID de transaction Didit d'un transfert Travel Rule à faire avancer lorsque la preuve est vérifiée.",
            "nullable": true
          },
          "satoshi_deposit_address": {
            "type": "string",
            "description": "Optionnel. Une adresse de dépôt que vous contrôlez ; la fournir active la méthode de preuve SATOSHI_TEST.",
            "maxLength": 128
          },
          "callback_url": {
            "type": "string",
            "description": "Optionnel. URL http(s) absolue vers laquelle le widget renvoie le client une fois terminé.",
            "maxLength": 512
          },
          "expires_in_minutes": {
            "type": "integer",
            "description": "Optionnel. Durée de validité du lien généré, en minutes. Automatiquement prolongée pour couvrir la fenêtre du test Satoshi lorsque SATOSHI_TEST est proposé.",
            "default": 60,
            "minimum": 5,
            "maximum": 10080
          }
        }
      },
      "TravelRuleWidgetSessionResponse": {
        "type": "object",
        "properties": {
          "widget_session_id": {
            "type": "string",
            "format": "uuid"
          },
          "token": {
            "type": "string",
            "description": "Token de session opaque intégré dans l'URL du widget."
          },
          "url": {
            "type": "string",
            "description": "L'URL du widget hébergé de propriété du portefeuille. Ouvrez-la telle quelle dans le navigateur du système (jamais à l'intérieur d'une webview de SDK mobile)."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TravelRuleWidgetContext": {
        "type": "object",
        "properties": {
          "vasp_name": {
            "type": "string",
            "description": "Raison sociale issue de votre profil VASP, affichée au client dans le widget. Vide lorsqu'aucun profil n'existe."
          },
          "wallet_address": {
            "type": "string"
          },
          "chain": {
            "type": "string",
            "description": "La blockchain avec laquelle la session a été créée, telle que vous l'avez envoyée."
          },
          "chain_family": {
            "type": "string",
            "nullable": true,
            "enum": [
              "EVM",
              "BTC",
              "SOL",
              "TRON",
              null
            ],
            "description": "La famille de clés associée à la blockchain : EVM (Ethereum, BNB Chain, Polygon, Arbitrum, Base, Optimism, Avalanche, Linea et les autres blockchains EVM), BTC, SOL ou TRON. Une clé EVM contrôle la même adresse sur chaque blockchain EVM. Nul lorsqu'aucune signature ne peut être vérifiée sur la blockchain."
          },
          "holder_name": {
            "type": "string"
          },
          "allowed_methods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "MESSAGE_SIGNING",
                "SCREENSHOT",
                "SATOSHI_TEST",
                "SELF_DECLARATION"
              ]
            },
            "description": "Méthodes de preuve disponibles pour cette session. MESSAGE_SIGNING nécessite une chaîne avec un chain_family, SATOSHI_TEST nécessite un satoshi_deposit_address sur la session et une chaîne dont Didit peut relire les dépôts, SCREENSHOT nécessite le paramètre allow_screenshot_proof, et SELF_DECLARATION nécessite le paramètre allow_self_declaration."
          },
          "transfer_status": {
            "type": "string",
            "nullable": true,
            "description": "Statut du transfert Travel Rule associé. Null lorsque la session a été créée sans transaction_id."
          },
          "callback_url": {
            "type": "string",
            "description": "Endroit où le widget redirige le client une fois terminé. Vide si non défini."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Non nul une fois qu'une preuve a été vérifiée."
          },
          "proofs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TravelRuleWidgetProofSummary"
            }
          },
          "max_attempts": {
            "type": "integer",
            "description": "Preuves de portefeuille rejetées autorisées par cette session."
          },
          "attempts_used": {
            "type": "integer",
            "description": "Preuves rejetées jusqu'à présent."
          },
          "attempts_remaining": {
            "type": "integer",
            "description": "Lorsque la valeur est 0, lancer une autre preuve renvoie 409 et vous générez une nouvelle session de widget."
          },
          "customization": {
            "type": "object",
            "nullable": true,
            "description": "La personnalisation en marque blanche de l'application (couleurs, logo, famille de polices) lorsque la marque blanche est activée - le widget s'affiche avec la même identité visuelle que le workflow de vérification. Null dans le cas contraire."
          }
        }
      },
      "TravelRuleWidgetProofSummary": {
        "type": "object",
        "properties": {
          "proof_id": {
            "type": "string",
            "format": "uuid"
          },
          "method": {
            "type": "string",
            "enum": [
              "MESSAGE_SIGNING",
              "SATOSHI_TEST",
              "SCREENSHOT",
              "SELF_DECLARATION"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "VERIFIED",
              "REJECTED",
              "EXPIRED"
            ],
            "description": "PENDING : l'utilisateur final a choisi cette méthode et la preuve n'est pas encore tranchée. Une signature échouée ou un dépôt test non lisible ou non encore confirmé maintient la preuve PENDING avec un failure_reason, afin que l'utilisateur final puisse réessayer ; un dépôt SATOSHI_TEST soumis est revérifié automatiquement jusqu'à la clôture de sa fenêtre, et une SCREENSHOT soumise attend votre examen. VERIFIED : la propriété est prouvée. REJECTED : le dépôt test est véritablement incorrect (autre expéditeur, montant vers l'adresse de dépôt différent de celui attendu, antérieur au défi, ou transaction ayant déjà prouvé un autre portefeuille) ou votre réviseur a refusé la capture d'écran ; failure_reason indique la cause. Une preuve rejetée est définitive et consomme l'une des tentatives de la session. EXPIRED : la preuve ne peut plus être tranchée (sa fenêtre s'est fermée, l'utilisateur final a changé de méthode, la session du widget a expiré ou le titulaire du portefeuille a changé) ; failure_reason indique la cause."
          },
          "wallet_address": {
            "type": "string"
          },
          "chain": {
            "type": "string",
            "description": "Identifiant canonique de la blockchain de l'entrée du carnet d'adresses à laquelle la preuve se rapporte, par ex. ETH, BTC, SOL, TRX."
          },
          "deposit_address": {
            "type": "string",
            "nullable": true,
            "description": "Adresse de dépôt à laquelle le client doit envoyer le montant du test Satoshi. Présent uniquement sur une preuve SATOSHI_TEST."
          },
          "expected_amount": {
            "type": "string",
            "nullable": true,
            "description": "Montant on-chain exact, dans la devise native du dépôt, auquel le dépôt de test Satoshi doit correspondre. Présent uniquement sur une preuve SATOSHI_TEST."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date limite pour la fenêtre du test Satoshi propre à cette preuve. Présent uniquement sur une preuve SATOSHI_TEST ; l'expires_at propre à la session de widget est prolongé pour la couvrir lorsque SATOSHI_TEST est proposé."
          },
          "challenge": {
            "type": "string",
            "nullable": true,
            "description": "Message émis par Didit que le client signe avec son portefeuille. Présent uniquement sur une preuve MESSAGE_SIGNING."
          },
          "rejection_reason": {
            "type": "string",
            "description": "Raison pour laquelle la preuve a été refusée, sous forme de phrase en anglais pour l'utilisateur final. Présente uniquement lorsque `status` est REJECTED ; vide lorsque votre réviseur a refusé une capture d'écran (votre note reste chez vous)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "attempts": {
            "type": "integer",
            "description": "Nombre de fois où des éléments probants ont été soumis pour ce justificatif (signatures, identifiants de transaction, téléversements)."
          },
          "failure_reason": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleWalletProofFailureReason"
              }
            ],
            "description": "Raison pour laquelle la dernière tentative a échoué, ou raison pour laquelle la preuve a été clôturée. Vide lorsque rien n'a échoué."
          }
        }
      },
      "CaseSubject": {
        "type": "object",
        "nullable": true,
        "description": "L'utilisateur ou l'entreprise unique auquel ou à laquelle le dossier est rattaché.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "user",
              "business"
            ]
          },
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "external_id": {
            "type": "string",
            "nullable": true,
            "description": "Le vendor_data du sujet."
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "Code pays à trois lettres du sujet (ISO 3166-1 alpha-3), ou null lorsqu'il n'est pas connu. Pour une entreprise, son pays de constitution. Pour une personne, le pays de délivrance d'un document d'identité issu de ses vérifications ; une personne possédant des documents de plusieurs pays affiche l'un d'eux, et des codes de document OACI tels que `XXA` peuvent apparaître.",
            "example": "ESP"
          },
          "portrait": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL signée de courte durée de l'image du portrait de la personne. Toujours null pour une entreprise, et null pour une personne sans portrait. L'URL expire, téléchargez donc l'image lorsque vous consultez le dossier plutôt que d'enregistrer l'URL."
          }
        }
      },
      "CaseAssignee": {
        "type": "object",
        "nullable": true,
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "full_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          }
        }
      },
      "CaseBlueprintSummary": {
        "type": "object",
        "nullable": true,
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "maxLength": 24
          }
        }
      },
      "CaseContentConfig": {
        "type": "object",
        "description": "Les six sections activables qui déterminent les onglets et les champs affichés sur la page du dossier. Les sections ou clés inconnues sont rejetées.",
        "properties": {
          "checklist": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "optional": {
                "type": "boolean",
                "description": "Si true, un dossier peut être résolu avec des éléments de liste de contrôle incomplets."
              },
              "items": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": {
                      "type": "string",
                      "maxLength": 255
                    },
                    "order": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "aml_control": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "financial": {
                "type": "boolean"
              },
              "identity": {
                "type": "boolean"
              }
            }
          },
          "identity": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "personal_information": {
                "type": "boolean"
              },
              "applicant_tags": {
                "type": "boolean"
              },
              "contact_information": {
                "type": "boolean"
              },
              "risk_overview": {
                "type": "boolean"
              },
              "poi_documents": {
                "type": "boolean"
              },
              "poa_documents": {
                "type": "boolean"
              }
            }
          },
          "verifications": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "summary": {
                "type": "boolean"
              }
            }
          },
          "reporting": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "fiu_reports": {
                "type": "boolean"
              }
            }
          },
          "financial": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "payment_methods": {
                "type": "boolean"
              },
              "transactions": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "CaseNote": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "comment": {
            "type": "string"
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "actor_name": {
            "type": "string",
            "nullable": true
          },
          "mentioned_emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "is_internal": {
            "type": "boolean"
          },
          "attachments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "s3_key": {
                  "type": "string"
                },
                "filename": {
                  "type": "string"
                },
                "file_size": {
                  "type": "integer"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CaseEvent": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "CREATED",
              "STATUS_CHANGED",
              "ASSIGNED",
              "UNASSIGNED",
              "RESOLVED",
              "REOPENED",
              "LINK_ADDED",
              "LINK_REMOVED",
              "NOTE_ADDED",
              "NOTE_PINNED",
              "NOTE_UNPINNED",
              "PRIORITY_CHANGED",
              "DUE_DATE_CHANGED",
              "TAG_ADDED",
              "TAG_REMOVED",
              "ESCALATED",
              "TRANSFERRED",
              "CHECKLIST_COMPLETED",
              "REPORT_CREATED",
              "REPORT_FINALIZED",
              "SUBMITTED_FOR_APPROVAL",
              "APPROVAL_GRANTED",
              "APPROVAL_REJECTED",
              "ENTITY_ACTION",
              "APPROVAL_INVALIDATED",
              "CUSTOMER_REQUEST",
              "STAGE_CHANGED",
              "TEAM_CHANGED",
              "CHECKER_ASSIGNED",
              "CHECKER_UNASSIGNED"
            ]
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "actor_name": {
            "type": "string",
            "nullable": true
          },
          "previous_status": {
            "type": "string",
            "enum": [
              "OPEN",
              "AWAITING_USER",
              "RESOLVED"
            ],
            "nullable": true
          },
          "new_status": {
            "type": "string",
            "enum": [
              "OPEN",
              "AWAITING_USER",
              "RESOLVED"
            ],
            "nullable": true
          },
          "metadata": {
            "type": "object"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CaseLink": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "linked_entity_type": {
            "type": "string",
            "enum": [
              "session",
              "business_session",
              "transaction"
            ],
            "nullable": true
          },
          "linked_entity_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "linked_entity_summary": {
            "type": "object",
            "nullable": true,
            "description": "session_id/session_number/status pour les liens de session et business_session ; uuid/txn_id/status pour les liens de transaction."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CaseChecklistItem": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string",
            "maxLength": 255
          },
          "is_completed": {
            "type": "boolean"
          },
          "completed_by": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "order": {
            "type": "integer"
          }
        }
      },
      "CaseBlueprintListItem": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "maxLength": 24
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "assignment_method": {
            "type": "string",
            "enum": [
              "MANUAL",
              "AUTOMATIC"
            ]
          },
          "assignee_pool": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "max_active_cases": {
            "type": "integer",
            "nullable": true
          },
          "escalation_enabled": {
            "type": "boolean"
          },
          "transfer_enabled": {
            "type": "boolean"
          },
          "require_resolution_note": {
            "type": "boolean"
          },
          "is_active": {
            "type": "boolean"
          },
          "preset_key": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "version": {
            "type": "integer",
            "readOnly": true
          },
          "default_deadline_hours": {
            "type": "integer",
            "nullable": true,
            "minimum": 1,
            "maximum": 8760
          }
        }
      },
      "CaseBlueprintDetail": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "maxLength": 24
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "assignment_method": {
            "type": "string",
            "enum": [
              "MANUAL",
              "AUTOMATIC"
            ]
          },
          "assignee_pool": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "max_active_cases": {
            "type": "integer",
            "nullable": true
          },
          "escalation_enabled": {
            "type": "boolean"
          },
          "transfer_enabled": {
            "type": "boolean"
          },
          "require_resolution_note": {
            "type": "boolean"
          },
          "is_active": {
            "type": "boolean"
          },
          "preset_key": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "escalation_blueprint": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "escalation_blueprint_name": {
            "type": "string",
            "nullable": true
          },
          "four_eyes_checker_blueprint": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "four_eyes_checker_blueprint_name": {
            "type": "string",
            "nullable": true
          },
          "content_config": {
            "type": "object",
            "description": "Les six sections activables qui déterminent les onglets et les champs affichés sur la page du dossier. Les sections ou clés inconnues sont rejetées.",
            "properties": {
              "checklist": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "optional": {
                    "type": "boolean",
                    "description": "Si true, un dossier peut être résolu avec des éléments de liste de contrôle incomplets."
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "label": {
                          "type": "string",
                          "maxLength": 255
                        },
                        "order": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              },
              "aml_control": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "financial": {
                    "type": "boolean"
                  },
                  "identity": {
                    "type": "boolean"
                  }
                }
              },
              "identity": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "personal_information": {
                    "type": "boolean"
                  },
                  "applicant_tags": {
                    "type": "boolean"
                  },
                  "contact_information": {
                    "type": "boolean"
                  },
                  "risk_overview": {
                    "type": "boolean"
                  },
                  "poi_documents": {
                    "type": "boolean"
                  },
                  "poa_documents": {
                    "type": "boolean"
                  }
                }
              },
              "verifications": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "summary": {
                    "type": "boolean"
                  }
                }
              },
              "reporting": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "fiu_reports": {
                    "type": "boolean"
                  }
                }
              },
              "financial": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "payment_methods": {
                    "type": "boolean"
                  },
                  "transactions": {
                    "type": "boolean"
                  }
                }
              }
            }
          },
          "creation_sources": {
            "type": "array",
            "description": "Connecteurs acheminant actuellement de nouveaux dossiers vers ce modèle.",
            "items": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string",
                  "enum": [
                    "aml",
                    "rule",
                    "workflow"
                  ]
                },
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "receives_escalation_from": {
            "type": "array",
            "description": "Autres modèles dont la cible d'escalade pointe vers celui-ci.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "version": {
            "type": "integer",
            "readOnly": true
          },
          "default_deadline_hours": {
            "type": "integer",
            "nullable": true,
            "minimum": 1,
            "maximum": 8760
          }
        }
      },
      "CaseListItem": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "case_number": {
            "type": "string",
            "nullable": true,
            "description": "Attribué automatiquement, par ex. CS-0001."
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "OPEN",
              "AWAITING_USER",
              "RESOLVED"
            ]
          },
          "resolution": {
            "type": "string",
            "enum": [
              "FALSE_POSITIVE",
              "VALID_THREAT",
              "INCONCLUSIVE",
              "REQUIREMENTS_NOT_MET",
              "REQUIREMENTS_SATISFIED"
            ],
            "nullable": true
          },
          "pending_resolution": {
            "type": "object",
            "nullable": true,
            "description": "Défini uniquement lorsqu'une résolution à 4 yeux est préparée sur le blueprint du checker, en attente d'approbation ou de rejet.",
            "properties": {
              "resolution": {
                "type": "string",
                "enum": [
                  "FALSE_POSITIVE",
                  "VALID_THREAT",
                  "INCONCLUSIVE",
                  "REQUIREMENTS_NOT_MET",
                  "REQUIREMENTS_SATISFIED"
                ]
              },
              "resolution_notes": {
                "type": "string",
                "nullable": true
              },
              "maker_email": {
                "type": "string",
                "format": "email",
                "nullable": true,
                "description": "E-mail du responsable qui a soumis la résolution. Null lorsqu'une clé API l'a soumise : cette résolution n'a pas d'auteur enregistré, donc approve et reject-approval renvoient 403 pour tous les appelants."
              },
              "maker_name": {
                "type": "string",
                "nullable": true
              },
              "maker_user_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "UUID d'utilisateur du membre qui a soumis la résolution. Null lorsqu'une clé API l'a soumise. Ce membre ne peut pas être désigné comme `checker`."
              },
              "maker_blueprint_id": {
                "type": "string",
                "format": "uuid"
              },
              "staged_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "checker": {
            "$ref": "#/components/schemas/CaseChecker"
          },
          "priority": {
            "type": "string",
            "enum": [
              "LOW",
              "MEDIUM",
              "HIGH"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "MANUAL",
              "AML_SCREENING",
              "TRANSACTION_RULE",
              "WORKFLOW_BUILDER"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "subject": {
            "$ref": "#/components/schemas/CaseSubject"
          },
          "assigned_to": {
            "$ref": "#/components/schemas/CaseAssignee"
          },
          "assigned_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "team": {
            "$ref": "#/components/schemas/CaseTeamSummary"
          },
          "due_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resolved_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_by_email": {
            "type": "string",
            "nullable": true
          },
          "created_by_name": {
            "type": "string",
            "nullable": true
          },
          "blueprint": {
            "$ref": "#/components/schemas/CaseBlueprintSummary"
          },
          "links_count": {
            "type": "integer"
          },
          "notes_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "application_id": {
            "type": "string",
            "format": "uuid"
          },
          "application_name": {
            "type": "string"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "organization_name": {
            "type": "string"
          }
        }
      },
      "CaseDetail": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "case_number": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "OPEN",
              "AWAITING_USER",
              "RESOLVED"
            ]
          },
          "resolution": {
            "type": "string",
            "enum": [
              "FALSE_POSITIVE",
              "VALID_THREAT",
              "INCONCLUSIVE",
              "REQUIREMENTS_NOT_MET",
              "REQUIREMENTS_SATISFIED"
            ],
            "nullable": true
          },
          "resolution_notes": {
            "type": "string",
            "nullable": true
          },
          "priority": {
            "type": "string",
            "enum": [
              "LOW",
              "MEDIUM",
              "HIGH"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "MANUAL",
              "AML_SCREENING",
              "TRANSACTION_RULE",
              "WORKFLOW_BUILDER"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "subject": {
            "$ref": "#/components/schemas/CaseSubject"
          },
          "assigned_to": {
            "$ref": "#/components/schemas/CaseAssignee"
          },
          "assigned_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "team": {
            "$ref": "#/components/schemas/CaseTeamSummary"
          },
          "due_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resolved_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resolved_by_email": {
            "type": "string",
            "nullable": true
          },
          "pending_resolution": {
            "type": "object",
            "nullable": true,
            "description": "Défini uniquement lorsqu'une résolution à 4 yeux est préparée sur le blueprint du checker, en attente d'approbation ou de rejet.",
            "properties": {
              "resolution": {
                "type": "string",
                "enum": [
                  "FALSE_POSITIVE",
                  "VALID_THREAT",
                  "INCONCLUSIVE",
                  "REQUIREMENTS_NOT_MET",
                  "REQUIREMENTS_SATISFIED"
                ]
              },
              "resolution_notes": {
                "type": "string",
                "nullable": true
              },
              "maker_email": {
                "type": "string",
                "format": "email",
                "nullable": true,
                "description": "E-mail du responsable qui a soumis la résolution. Null lorsqu'une clé API l'a soumise : cette résolution n'a pas d'auteur enregistré, donc approve et reject-approval renvoient 403 pour tous les appelants."
              },
              "maker_name": {
                "type": "string",
                "nullable": true
              },
              "maker_user_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "UUID d'utilisateur du membre qui a soumis la résolution. Null lorsqu'une clé API l'a soumise. Ce membre ne peut pas être désigné comme `checker`."
              },
              "maker_blueprint_id": {
                "type": "string",
                "format": "uuid"
              },
              "staged_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "checker": {
            "$ref": "#/components/schemas/CaseChecker"
          },
          "metadata": {
            "type": "object"
          },
          "blueprint": {
            "$ref": "#/components/schemas/CaseBlueprintDetail"
          },
          "notes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseNote"
            },
            "description": "50 notes les plus récentes."
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseEvent"
            },
            "description": "100 événements les plus récents."
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseLink"
            }
          },
          "links_count": {
            "type": "integer"
          },
          "notes_count": {
            "type": "integer"
          },
          "checklist_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseChecklistItem"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ReportTemplateDetail": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "jurisdiction": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "Code pays ISO 3166-1 alpha-2."
          },
          "report_type": {
            "type": "string",
            "enum": [
              "SAR",
              "STR",
              "CTR",
              "TTR",
              "UTR",
              "IFT",
              "CBR",
              "TFR"
            ]
          },
          "report_type_display": {
            "type": "string"
          },
          "field_config": {
            "type": "object",
            "description": "Valeurs par défaut réutilisables des en-têtes goAML. Champs obligatoires au niveau du modèle : rentity_id, submission_code et currency_code_local (3 lettres). Facultatif : enabled_fields (quels blocs de rapport facultatifs inclure) ainsi que les valeurs par défaut pour reporting_person, location, reason et action. Les champs d'en-tête propres au dépôt (action, submission_date, transactions, jurisdiction) sont appliqués lors de la validation ou de la finalisation du rapport, et non sur le modèle."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RegulatoryReportDetail": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "case_uuid": {
            "type": "string",
            "format": "uuid"
          },
          "case_number": {
            "type": "string",
            "nullable": true
          },
          "report_type": {
            "type": "string",
            "enum": [
              "SAR",
              "STR",
              "CTR",
              "TTR",
              "UTR",
              "IFT",
              "CBR",
              "TFR"
            ]
          },
          "report_type_display": {
            "type": "string"
          },
          "report_code": {
            "type": "string",
            "description": "Code de rapport goAML dérivé de report_type, par ex. STR, CTR, BCR."
          },
          "report_number": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "VALIDATED",
              "FINALIZED"
            ]
          },
          "status_display": {
            "type": "string"
          },
          "jurisdiction": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "rentity_id": {
            "type": "string",
            "nullable": true,
            "description": "Identifiant de l'entité déclarante délivré par la CRF."
          },
          "rentity_branch": {
            "type": "string",
            "nullable": true
          },
          "submission_code": {
            "type": "string",
            "enum": [
              "E",
              "M"
            ]
          },
          "entity_reference": {
            "type": "string",
            "nullable": true
          },
          "fiu_ref_number": {
            "type": "string",
            "nullable": true
          },
          "currency_code_local": {
            "type": "string",
            "minLength": 3,
            "maxLength": 3,
            "nullable": true
          },
          "submission_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "reporting_person": {
            "type": "object"
          },
          "location": {
            "type": "object"
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "action": {
            "type": "string",
            "nullable": true
          },
          "activity": {
            "type": "string",
            "nullable": true
          },
          "narrative": {
            "type": "object",
            "description": "Sections narratives des cinq W.",
            "properties": {
              "who": {
                "type": "string"
              },
              "what": {
                "type": "string"
              },
              "when": {
                "type": "string"
              },
              "where": {
                "type": "string"
              },
              "why": {
                "type": "string"
              },
              "how": {
                "type": "string"
              }
            }
          },
          "report_indicators": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "included_fields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "transactions": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "validation_errors": {
            "type": "array",
            "description": "Résultat de la validation la plus récente ; chaque entrée est un objet {field, message}.",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          },
          "validated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "finalized_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_by_email": {
            "type": "string",
            "nullable": true
          },
          "created_by_name": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TransactionRuleCondition": {
        "type": "object",
        "required": [
          "field",
          "operator"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "Chemin du champ de transaction à évaluer. Champs principaux : amount, currency, direction, action_type, score, severity, transaction_type, payment_details, preferred_currency_amount (se rabat sur amount_in_default_currency), default_currency_code, subject_country, counterparty_country, subject_vendor_data, counterparty_vendor_data, subject_device_fingerprint, counterparty_device_fingerprint, subject_browser_family, subject_browser_version, subject_platform, subject_accept_language, subject_session_age_ms, subject_ip_country, counterparty_ip_country, subject_ip_address, counterparty_ip_address, subject_payment_method_type, subject_payment_method_country, subject_payment_method_fingerprint, subject_payment_method_account_id (et les équivalents counterparty_payment_method_*), travel_rule_status, travel_rule_required, travel_rule_obligations_count, counterparty_dd_status (votre décision sur la contrepartie Travel Rule : APPROVED, RESTRICTED ou BLOCKED, une entité suivant celle de sa marque), counterparty_risk_level (LOW, MEDIUM ou HIGH ; HIGH tant que votre propre filtrage de la contrepartie est signalé), counterparty_jurisdiction (le pays du VASP de la contrepartie), counterparty_responsiveness (RESPONSIVE, UNRESPONSIVE ou UNKNOWN), subject_days_since_previous_transaction, tags, et custom_values.<key> pour toute clé fournie dans custom_properties lors de la création de la transaction. Les champs de code pays acceptent ISO-2 ou ISO-3 ; les deux côtés sont normalisés en ISO-3 avant la comparaison."
          },
          "operator": {
            "type": "string",
            "enum": [
              "eq",
              "ne",
              "gt",
              "gte",
              "lt",
              "lte",
              "in",
              "not_in",
              "contains",
              "not_contains",
              "contains_any",
              "regex",
              "fuzzy_match",
              "exists",
              "is_not_empty",
              "is_not_null",
              "not_exists",
              "is_empty",
              "is_null"
            ],
            "description": "Opérateur de comparaison. in/not_in testent l'appartenance (la valeur peut être une liste ou un scalaire unique). contains/not_contains sont des vérifications de sous-chaîne insensibles à la casse par rapport à une valeur de chaîne. contains_any prend une liste de chaînes et correspond lorsque l'une d'elles est une sous-chaîne insensible à la casse de la valeur du champ. regex fait correspondre le motif de la valeur avec le champ. fuzzy_match compare avec la chaîne de valeur selon le seuil de `score` requis (0-100). gt/gte/lt/lte ne correspondent jamais lorsque l'un des côtés est manquant. exists/is_not_empty/is_not_null (alias) et not_exists/is_empty/is_null (alias) sont des vérifications de présence qui ignorent `value`."
          },
          "value": {
            "description": "Valeur de comparaison. Sa forme dépend de l'opérateur et de value_type ; omettez-la pour les opérateurs de vérification de présence. Tout autre opérateur nécessite une valeur qui n'est pas `null` ou une liste vide, sinon la règle est refusée avec `400`. `contains_any` nécessite une liste de chaînes, et `contains`, `not_contains` et `regex` nécessitent une seule chaîne."
          },
          "value_type": {
            "type": "string",
            "enum": [
              "list",
              "field",
              "relative_date"
            ],
            "description": "Interprétation de la valeur optionnelle. `list` : la valeur est un UUID de liste et les entrées de la liste deviennent la valeur de comparaison. `field` : la valeur est un chemin vers un autre champ, comparé champ à champ. `relative_date` : la valeur est un objet de date relative, par exemple {\"direction\": \"past\", \"unit\": \"days\", \"amount\": 30}."
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Requis lorsque l'opérateur est fuzzy_match : le seuil de similarité de 0 à 100."
          },
          "group_index": {
            "type": "integer",
            "description": "Logique groupée optionnelle. Lorsqu'une condition porte group_index, les conditions partageant un index forment un groupe et l'évaluation groupée remplace evaluation_mode."
          },
          "group_logic": {
            "type": "string",
            "enum": [
              "AND",
              "OR"
            ],
            "default": "AND",
            "description": "Manière dont les conditions se combinent AU SEIN d'un groupe."
          },
          "groups_logic": {
            "type": "string",
            "enum": [
              "AND",
              "OR"
            ],
            "default": "OR",
            "description": "Manière dont les résultats des groupes se combinent ENTRE les groupes. Lu à partir de la première condition."
          }
        },
        "description": "Une condition lit uniquement la transaction en cours d'évaluation - elle ne filtre jamais la fenêtre d'agrégation."
      },
      "TransactionRuleAggregation": {
        "type": "object",
        "required": [
          "value"
        ],
        "properties": {
          "metric": {
            "type": "string",
            "enum": [
              "count",
              "sum",
              "max",
              "min",
              "avg",
              "distinct_count"
            ],
            "default": "count",
            "description": "Manière dont les transactions historiques correspondantes sont agrégées. unique_count est accepté en tant qu'alias de distinct_count."
          },
          "field": {
            "type": "string",
            "default": "amount",
            "description": "Champ agrégé par sum/max/min/avg/distinct_count. Ignoré pour count."
          },
          "operator": {
            "type": "string",
            "enum": [
              "eq",
              "ne",
              "gt",
              "gte",
              "lt",
              "lte"
            ],
            "default": "eq",
            "description": "Comparaison appliquée à la métrique calculée."
          },
          "value": {
            "type": "number",
            "description": "Seuil auquel la métrique calculée est comparée."
          },
          "window": {
            "type": "string",
            "pattern": "^\\d+(m|h|d)$",
            "default": "1d",
            "description": "Fenêtre rétrospective se terminant à la date txn_date de la transaction : <N>m (MINUTES, et non mois), <N>h (heures) ou <N>d (jours), par ex. 30m, 24h, 7d, 30d."
          },
          "filters": {
            "type": "object",
            "additionalProperties": true,
            "description": "Restreint les transactions historiques qui sont agrégées. Les clés sont des chemins de champs issus du catalogue de champs de conditions ; une valeur de \"__current__\" prend la valeur du même champ sur la transaction en cours d'évaluation (par exemple {\"subject_vendor_data\": \"__current__\"} restreint la fenêtre au même sujet), et une liste indique une appartenance. Les enregistrements dépourvus de la valeur de regroupement ne sont jamais regroupés ensemble : lorsque la transaction en cours d'évaluation n'a pas de valeur pour un champ \"__current__\" (pas de contrepartie, pas d'empreinte d'appareil), l'agrégation ne correspond pas, quel que soit son opérateur. Les filtres comparent UNIQUEMENT par égalité ou appartenance - il n'y a pas de filtre lt/gte, donc une plage telle que \"transactions historiques inférieures à 10 000\" ne peut pas être formulée ici. Définissez plutôt la plage sur la métrique (la métrique max avec l'opérateur lt conserve chaque transaction de la fenêtre sous le seuil)."
          }
        },
        "description": "Contrôle de vélocité sur les transactions historiques de l'application dans la fenêtre. Chaque entrée d'agrégation doit correspondre pour que la règle s'applique, quel que soit evaluation_mode. Une agrégation ne restreint que la fenêtre ; la transaction en cours d'évaluation est restreinte par le périmètre et les conditions, donc répétez la direction, la devise ou le transaction_type sur les deux moitiés lorsque la règle les prévoit."
      },
      "TransactionRuleScope": {
        "type": "object",
        "properties": {
          "transaction_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Restreindre aux types de transaction, par ex. finance, kyc, travel_rule, user_event. Vide ou manquant = aucune restriction."
          },
          "directions": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "INBOUND",
                "OUTBOUND"
              ]
            },
            "description": "Restreindre aux directions de transaction (insensible à la casse à l'écriture)."
          },
          "action_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Restreindre à vos valeurs action_type, par ex. withdrawal, deposit."
          }
        },
        "description": "À quelles transactions la règle s'applique. Seules ces trois clés sont acceptées."
      },
      "TransactionRuleAction": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/TransactionRuleActionAddScore"
          },
          {
            "$ref": "#/components/schemas/TransactionRuleActionChangeStatus"
          },
          {
            "$ref": "#/components/schemas/TransactionRuleActionAddTags"
          },
          {
            "$ref": "#/components/schemas/TransactionRuleActionAddNote"
          },
          {
            "$ref": "#/components/schemas/TransactionRuleActionAddToList"
          },
          {
            "$ref": "#/components/schemas/TransactionRuleActionOpenCase"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "add_score": "#/components/schemas/TransactionRuleActionAddScore",
            "change_status": "#/components/schemas/TransactionRuleActionChangeStatus",
            "add_tags": "#/components/schemas/TransactionRuleActionAddTags",
            "add_note": "#/components/schemas/TransactionRuleActionAddNote",
            "add_to_list": "#/components/schemas/TransactionRuleActionAddToList",
            "open_case": "#/components/schemas/TransactionRuleActionOpenCase"
          }
        },
        "description": "Une action de règle. Une règle peut en comporter plusieurs ; elles sont toutes appliquées ensemble lorsqu'elle correspond. Les règles en mode TEST enregistrent ce qu'elles auraient fait sans appliquer aucune action."
      },
      "TransactionRuleCreateRequest": {
        "type": "object",
        "required": [
          "title",
          "category",
          "mode"
        ],
        "properties": {
          "title": {
            "type": "string",
            "description": "Nom de la règle. Unique par application parmi les règles non supprimées ; les doublons renvoient 400."
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "description": "Thématique de risque utilisée pour le regroupement et les rapports, par ex. finance, aml_ctf, anomaly_detection, fatf, device_intelligence, crypto_monitoring, travel_rule, responsible_gaming, e_commerce."
          },
          "mode": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "DISABLED",
              "TEST"
            ],
            "description": "ACTIVE évalue en direct. TEST évalue et enregistre les exécutions de règles mais ne modifie jamais le score ni le statut - le mode de départ recommandé. DISABLED est ignoré."
          },
          "evaluation_mode": {
            "type": "string",
            "enum": [
              "ALL",
              "ANY"
            ],
            "default": "ALL",
            "description": "Indique si chaque condition doit correspondre (ALL) ou au moins une (ANY). Ignoré lorsque les conditions utilisent group_index."
          },
          "scope": {
            "$ref": "#/components/schemas/TransactionRuleScope"
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleCondition"
            }
          },
          "aggregation": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAggregation"
            }
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAction"
            }
          },
          "metadata": {
            "type": "object",
            "description": "Métadonnées libres stockées sur la règle."
          }
        },
        "description": "Crée une règle CUSTOM. Les règles en mode ACTIVE prennent effet immédiatement pour les nouvelles transactions - créez-les d'abord en mode TEST et effectuez un backtest au préalable."
      },
      "TransactionRuleUpdateRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Nom de la règle. Unique par application parmi les règles non supprimées ; les doublons renvoient 400."
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "description": "Thématique de risque utilisée pour le regroupement et les rapports, par ex. finance, aml_ctf, anomaly_detection, fatf, device_intelligence, crypto_monitoring, travel_rule, responsible_gaming, e_commerce."
          },
          "mode": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "DISABLED",
              "TEST"
            ],
            "description": "ACTIVE évalue en direct. TEST évalue et enregistre les exécutions de règles mais ne modifie jamais le score ni le statut - le mode de départ recommandé. DISABLED est ignoré."
          },
          "evaluation_mode": {
            "type": "string",
            "enum": [
              "ALL",
              "ANY"
            ],
            "default": "ALL",
            "description": "Indique si chaque condition doit correspondre (ALL) ou au moins une (ANY). Ignoré lorsque les conditions utilisent group_index."
          },
          "scope": {
            "$ref": "#/components/schemas/TransactionRuleScope"
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleCondition"
            }
          },
          "aggregation": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAggregation"
            }
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAction"
            }
          },
          "metadata": {
            "type": "object",
            "description": "Métadonnées libres stockées sur la règle."
          }
        },
        "description": "Mise à jour partielle. Les règles personnalisées acceptent tous les champs ; les règles de bibliothèque (PRESET) n'acceptent que mode - toute autre valeur renvoie 400."
      },
      "TransactionRuleDetail": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string",
            "description": "Nom de la règle. Unique par application parmi les règles non supprimées ; les doublons renvoient 400."
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "description": "Thématique de risque utilisée pour le regroupement et les rapports, par ex. finance, aml_ctf, anomaly_detection, fatf, device_intelligence, crypto_monitoring, travel_rule, responsible_gaming, e_commerce."
          },
          "mode": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "DISABLED",
              "TEST"
            ],
            "description": "ACTIVE évalue en direct. TEST évalue et enregistre les exécutions de règles mais ne modifie jamais le score ni le statut - le mode de départ recommandé. DISABLED est ignoré."
          },
          "evaluation_mode": {
            "type": "string",
            "enum": [
              "ALL",
              "ANY"
            ],
            "default": "ALL",
            "description": "Indique si chaque condition doit correspondre (ALL) ou au moins une (ANY). Ignoré lorsque les conditions utilisent group_index."
          },
          "scope": {
            "$ref": "#/components/schemas/TransactionRuleScope"
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleCondition"
            }
          },
          "aggregation": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAggregation"
            }
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAction"
            }
          },
          "metadata": {
            "type": "object",
            "description": "Métadonnées libres stockées sur la règle."
          },
          "severity": {
            "type": "string",
            "enum": [
              "UNKNOWN",
              "LOW",
              "MEDIUM",
              "HIGH",
              "CRITICAL"
            ],
            "nullable": true,
            "description": "Gravité informative portée par les règles de la bibliothèque ; non définissable sur les règles personnalisées."
          },
          "source": {
            "type": "string",
            "enum": [
              "PRESET",
              "CUSTOM"
            ],
            "description": "Les règles PRESET proviennent de la bibliothèque (installation/désinstallation, modifications du mode uniquement) ; les règles CUSTOM sont entièrement les vôtres."
          },
          "library_key": {
            "type": "string",
            "nullable": true,
            "description": "Identifiant stable de bibliothèque ; null pour les règles personnalisées."
          },
          "latest_triggered_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "run_count": {
            "type": "integer",
            "description": "Nombre de transactions correspondant à cette règle."
          },
          "approved_count": {
            "type": "integer"
          },
          "reviewed_count": {
            "type": "integer"
          },
          "declined_count": {
            "type": "integer"
          },
          "awaiting_user_count": {
            "type": "integer"
          },
          "approved_pct": {
            "type": "number"
          },
          "reviewed_pct": {
            "type": "number"
          },
          "declined_pct": {
            "type": "number"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TransactionRuleBacktestRequest": {
        "type": "object",
        "properties": {
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleCondition"
            },
            "default": []
          },
          "aggregation": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAggregation"
            },
            "default": []
          },
          "evaluation_mode": {
            "type": "string",
            "enum": [
              "ALL",
              "ANY"
            ],
            "default": "ALL"
          },
          "scope": {
            "$ref": "#/components/schemas/TransactionRuleScope"
          },
          "period_days": {
            "type": "integer",
            "minimum": 1,
            "maximum": 365,
            "default": 90
          }
        },
        "description": "Configuration de règle hypothétique à évaluer par rapport aux transactions récentes. En lecture seule et gratuit : rien n'est créé ni modifié. Envoyez les mêmes conditions, agrégation, mode d'évaluation (evaluation_mode) ET portée (scope) que la règle que vous prévoyez d'activer. Les conditions, l'agrégation et la portée omises n'ajoutent aucune contrainte propre ; omettre la portée peut inclure des sens ou des types de transaction que la règle enregistrée ignore. Si evaluation_mode est omis, la valeur par défaut est ALL (ce qui peut réduire les correspondances pour une règle ANY), et si period_days est omis, la valeur par défaut est de 90 jours, et non un historique illimité."
      },
      "TransactionRuleBacktestResult": {
        "type": "object",
        "properties": {
          "evaluated": {
            "type": "integer",
            "description": "Transactions évaluées (les plus récentes en premier, plafonnées)."
          },
          "matched": {
            "type": "integer",
            "description": "Transactions auxquelles la configuration aurait correspondu."
          },
          "affected_entities": {
            "type": "integer",
            "description": "Sujets distincts (par vendor_data) parmi les correspondances."
          },
          "period_days": {
            "type": "integer"
          }
        }
      },
      "TransactionRuleLibraryEntry": {
        "type": "object",
        "properties": {
          "library_key": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string"
          },
          "evaluation_mode": {
            "type": "string",
            "enum": [
              "ALL",
              "ANY"
            ]
          },
          "scope": {
            "$ref": "#/components/schemas/TransactionRuleScope"
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleCondition"
            }
          },
          "aggregation": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAggregation"
            }
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionRuleAction"
            }
          },
          "metadata": {
            "type": "object"
          },
          "bundle": {
            "type": "string",
            "nullable": true,
            "description": "Famille fonctionnelle, par ex. finance, aml_ctf, crypto_monitoring, travel_rule, responsible_gaming."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "industries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "source": {
            "type": "string"
          },
          "is_installed": {
            "type": "boolean",
            "description": "Indique si ce préréglage est actuellement installé sur l'application."
          }
        }
      },
      "TransactionRuleInstallRequest": {
        "type": "object",
        "properties": {
          "library_keys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Préréglages spécifiques à installer ou désinstaller."
          },
          "bundle": {
            "type": "string",
            "description": "Installer ou désinstaller à la place tous les préréglages de ce bundle."
          }
        },
        "description": "Fournissez library_keys OU bundle."
      },
      "TransactionRuleInstallResult": {
        "type": "object",
        "properties": {
          "installed_library_keys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "POST (installation) uniquement : modèles préconfigurés installés par cet appel."
          },
          "installed_count": {
            "type": "integer",
            "description": "POST (installation) uniquement."
          },
          "uninstalled_count": {
            "type": "integer",
            "description": "DELETE (désinstallation) uniquement : préconfigurations supprimées par cet appel."
          }
        }
      },
      "WalletScreeningResult": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "description": "Fournisseur ayant effectué le filtrage (par ex. `merklescience`, `crystal`)."
          },
          "screening_type": {
            "type": "string",
            "enum": [
              "WALLET_SCREENING"
            ],
            "description": "Toujours `WALLET_SCREENING` pour cet endpoint."
          },
          "risk_score": {
            "type": "integer",
            "description": "Score de risque normalisé de 0 à 100. Une valeur plus élevée indique une plus forte exposition à des entités à risque. Merkle Science note une adresse de 0 à 5, ce qui correspond à 0, 15, 35, 55, 75 ou 95."
          },
          "severity": {
            "type": "string",
            "enum": [
              "UNKNOWN",
              "LOW",
              "MEDIUM",
              "HIGH",
              "CRITICAL"
            ],
            "description": "Tranche de risque dérivée de `risk_score` : `0-9` UNKNOWN, `10-39` LOW, `40-69` MEDIUM, `70-89` HIGH, `90-100` CRITICAL. `UNKNOWN` est la tranche la plus basse, pas un état distinct d'absence de données : un `risk_score` de 0 (le cas courant d'une adresse propre) indique l'absence d'évaluation défavorable, tandis qu'un score non nul dans la plage 1-9 est un signal réel mais inférieur à LOW - lisez le `risk_score`, pas seulement la tranche. Ne traitez jamais `UNKNOWN` comme une évaluation confirmée de faible risque ou sans risque ; ne l'affichez pas comme une validation."
          },
          "status": {
            "type": "string",
            "enum": [
              "SCREENED",
              "PENDING",
              "ERROR"
            ],
            "description": "Statut du résultat du filtrage."
          },
          "summary": {
            "type": "string",
            "description": "Résumé lisible par l'utilisateur du résultat de filtrage."
          },
          "wallet_address": {
            "type": "string",
            "description": "L'adresse filtrée, renvoyée en écho."
          },
          "transaction_hash": {
            "type": "string",
            "nullable": true,
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Vaut toujours `null` sur un résultat de Filtrage des portefeuilles."
          },
          "blockchain": {
            "type": "string",
            "description": "La blockchain qui a été filtrée."
          },
          "block_timestamp": {
            "type": "string",
            "nullable": true,
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Vaut toujours `null` sur un résultat de Filtrage des portefeuilles."
          },
          "total_value_usd": {
            "type": "number",
            "nullable": true,
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Vaut toujours `null` sur un résultat de Filtrage des portefeuilles."
          },
          "fee_usd": {
            "type": "number",
            "nullable": true,
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Vaut toujours `null` sur un résultat de Filtrage des portefeuilles."
          },
          "sender_rows": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Toujours vide sur un résultat de Filtrage des portefeuilles."
          },
          "receiver_rows": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Toujours vide sur un résultat de Filtrage des portefeuilles."
          },
          "transaction_flows": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Toujours vide sur un résultat de Filtrage des portefeuilles."
          },
          "transaction_flows_status": {
            "type": "string",
            "nullable": true,
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Vaut toujours `null` sur un résultat de Filtrage des portefeuilles."
          },
          "transaction_flows_error": {
            "type": "string",
            "nullable": true,
            "description": "Champ de filtrage de transaction, partagé avec la structure du résultat. Vaut toujours `null` sur un résultat de Filtrage des portefeuilles."
          },
          "source_of_funds": {
            "type": "array",
            "description": "Provenance des fonds reçus par l'adresse, attribués par entité. Chaque entrée est une ventilation de l'exposition.",
            "items": {
              "type": "object",
              "properties": {
                "category": {
                  "type": "string",
                  "description": "Catégorie de risque normalisée, par exemple `exchange_licensed`, `dex`, `defi`, `payment_processor`, `mixer`, `darknet_market`, `sanctioned`, `stolen_funds`, `high_risk_exchange`."
                },
                "percentage": {
                  "type": "number",
                  "description": "Part de l'exposition totale du sens concerné, de 0 à 100."
                },
                "amount_usd": {
                  "type": "number",
                  "nullable": true,
                  "description": "Valeur en USD attribuée à cette entité."
                },
                "entity_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom de l'entité attribuée, par exemple une plateforme d'échange, un mixeur ou un groupe sous sanctions."
                },
                "entity_type": {
                  "type": "string",
                  "nullable": true,
                  "description": "Type d'entité du fournisseur (par ex. `Exchange`, `DeFi`, `Sanctions`, `Theft`)."
                },
                "entity_subtype": {
                  "type": "string",
                  "nullable": true,
                  "description": "Sous-type plus granulaire (par ex. `Mandatory KYC and AML`, `OFAC`, `Yield Aggregator`)."
                },
                "hops": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Nombre de sauts jusqu'à l'entité (1 pour une contrepartie directe), lorsque le fournisseur en signale un. Toujours `null` pour Merkle Science, qui indique uniquement si l'exposition est directe ou indirecte : utilisez `exposure_type`."
                },
                "description": {
                  "type": "string",
                  "nullable": true,
                  "description": "`entity_type / entity_subtype`, selon la façon dont le fournisseur qualifie l'entité."
                },
                "is_direct": {
                  "type": "boolean",
                  "description": "Vrai lorsque `exposure_type` est `direct`."
                },
                "exposure_direction": {
                  "type": "string",
                  "enum": [
                    "incoming",
                    "outgoing",
                    "connected"
                  ],
                  "description": "Indique si les fonds proviennent de (`incoming`) ou ont été envoyés vers (`outgoing`) cette entité."
                },
                "exposure_type": {
                  "type": "string",
                  "enum": [
                    "direct",
                    "indirect"
                  ],
                  "description": "Exposition `direct` (1 saut) ou `indirect` (multisauts)."
                },
                "provider_entity_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "L'identifiant propre au fournisseur pour l'entité."
                },
                "provider_entity_type_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "L'identifiant propre au fournisseur pour `entity_type`."
                },
                "provider_entity_subtype_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "L'identifiant propre au fournisseur pour `entity_subtype`."
                },
                "country": {
                  "type": "string",
                  "nullable": true,
                  "description": "Pays principal ISO 3166-1 alpha-2 de l'entité. Vide ou `null` lorsque le fournisseur ne le connaît pas."
                },
                "raw_amount": {
                  "type": "number",
                  "nullable": true,
                  "description": "Montant dans l'unité propre de l'actif, lorsque le fournisseur le transmet."
                },
                "raw_currency": {
                  "type": "string",
                  "nullable": true,
                  "description": "Unité de `raw_amount`, lorsque le fournisseur l'indique."
                }
              }
            }
          },
          "destination_of_funds": {
            "type": "array",
            "description": "Destination des fonds envoyés par l'adresse, attribués par entité. Même structure d'élément que `source_of_funds` avec `exposure_direction` = `outgoing`.",
            "items": {
              "type": "object",
              "properties": {
                "category": {
                  "type": "string",
                  "description": "Catégorie de risque normalisée, par exemple `exchange_licensed`, `dex`, `defi`, `payment_processor`, `mixer`, `darknet_market`, `sanctioned`, `stolen_funds`, `high_risk_exchange`."
                },
                "percentage": {
                  "type": "number",
                  "description": "Part de l'exposition totale du sens concerné, de 0 à 100."
                },
                "amount_usd": {
                  "type": "number",
                  "nullable": true,
                  "description": "Valeur en USD attribuée à cette entité."
                },
                "entity_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom de l'entité attribuée, par exemple une plateforme d'échange, un mixeur ou un groupe sous sanctions."
                },
                "entity_type": {
                  "type": "string",
                  "nullable": true,
                  "description": "Type d'entité du fournisseur (par ex. `Exchange`, `DeFi`, `Sanctions`, `Theft`)."
                },
                "entity_subtype": {
                  "type": "string",
                  "nullable": true,
                  "description": "Sous-type plus granulaire (par ex. `Mandatory KYC and AML`, `OFAC`, `Yield Aggregator`)."
                },
                "hops": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Nombre de sauts jusqu'à l'entité (1 pour une contrepartie directe), lorsque le fournisseur en signale un. Toujours `null` pour Merkle Science, qui indique uniquement si l'exposition est directe ou indirecte : utilisez `exposure_type`."
                },
                "description": {
                  "type": "string",
                  "nullable": true,
                  "description": "`entity_type / entity_subtype`, selon la façon dont le fournisseur qualifie l'entité."
                },
                "is_direct": {
                  "type": "boolean",
                  "description": "Vrai lorsque `exposure_type` est `direct`."
                },
                "exposure_direction": {
                  "type": "string",
                  "enum": [
                    "incoming",
                    "outgoing",
                    "connected"
                  ],
                  "description": "Indique si les fonds proviennent de (`incoming`) ou ont été envoyés vers (`outgoing`) cette entité."
                },
                "exposure_type": {
                  "type": "string",
                  "enum": [
                    "direct",
                    "indirect"
                  ],
                  "description": "Exposition `direct` (1 saut) ou `indirect` (multisauts)."
                },
                "provider_entity_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "L'identifiant propre au fournisseur pour l'entité."
                },
                "provider_entity_type_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "L'identifiant propre au fournisseur pour `entity_type`."
                },
                "provider_entity_subtype_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "L'identifiant propre au fournisseur pour `entity_subtype`."
                },
                "country": {
                  "type": "string",
                  "nullable": true,
                  "description": "Pays principal ISO 3166-1 alpha-2 de l'entité. Vide ou `null` lorsque le fournisseur ne le connaît pas."
                },
                "raw_amount": {
                  "type": "number",
                  "nullable": true,
                  "description": "Montant dans l'unité propre de l'actif, lorsque le fournisseur le transmet."
                },
                "raw_currency": {
                  "type": "string",
                  "nullable": true,
                  "description": "Unité de `raw_amount`, lorsque le fournisseur l'indique."
                }
              }
            }
          },
          "counterparty_connections": {
            "type": "array",
            "description": "Entités auxquelles le fournisseur attribue l'adresse filtrée. Pour Merkle Science, celles-ci proviennent des propres tags de propriétaire et d'utilisateur de l'adresse, la même entité peut donc apparaître deux fois, et elles ne comportent aucun flux de fonds : `received_usd`, `sent_usd`, `received_hops` et `sent_hops` sont `null` et `percentage` est 0. N'effectuez pas de routage sur `risk_level` ou `is_direct` ici : utilisez `sanctions_hit`, `dominant_risk_category` et `risk_factors[].is_high_risk` pour le verdict, et `exposure_type` dans `source_of_funds`/`destination_of_funds` pour le caractère direct.",
            "items": {
              "type": "object",
              "properties": {
                "entity_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom de l'entité attribuée."
                },
                "entity_type": {
                  "type": "string",
                  "nullable": true,
                  "description": "Type d'entité du fournisseur."
                },
                "entity_subtype": {
                  "type": "string",
                  "nullable": true,
                  "description": "Sous-type d'entité du fournisseur."
                },
                "risk_level": {
                  "type": "string",
                  "description": "En minuscules et dépendant du fournisseur. Pour Merkle Science, il s'agit du niveau de risque propre à l'adresse de 0 à 5 (`no_risk`, `low`, `medium_low`, `medium`, `high`, `critical`), relevé à `high` lorsque la catégorie de l'entité est à haut risque ; il ne s'agit pas d'un niveau distinct propre à l'entité."
                },
                "categories": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Catégories de risque normalisées de l'entité."
                },
                "received_usd": {
                  "type": "number",
                  "nullable": true,
                  "description": "Montant en USD reçu de l'entité, lorsque le fournisseur le signale."
                },
                "sent_usd": {
                  "type": "number",
                  "nullable": true,
                  "description": "Montant en USD envoyé à l'entité, lorsque le fournisseur le signale."
                },
                "received_hops": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Sauts jusqu'à l'entité du côté récepteur, lorsque le fournisseur les signale."
                },
                "sent_hops": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Sauts jusqu'à l'entité du côté émetteur, lorsque le fournisseur les signale."
                },
                "percentage": {
                  "type": "number",
                  "description": "Part de l'exposition de l'adresse, lorsque le fournisseur la signale ; sinon 0."
                },
                "is_direct": {
                  "type": "boolean",
                  "description": "Toujours `true` pour Merkle Science, dont les connexions sont des attributions plutôt que des contreparties."
                },
                "country": {
                  "type": "string",
                  "nullable": true,
                  "description": "Pays de l'entité, lorsqu'il est connu."
                },
                "provider_entity_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "L'identifiant propre au fournisseur pour l'entité."
                }
              }
            }
          },
          "network_nodes": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Nœuds du graphe d'exposition pour le filtrage des transactions. Vide pour un résultat de filtrage des portefeuilles."
          },
          "network_edges": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Arêtes du graphe d'exposition pour le filtrage des transactions. Vide pour un résultat de filtrage des portefeuilles."
          },
          "sanctions_hit": {
            "type": "boolean",
            "description": "Vrai si l'adresse a une exposition directe ou indirecte à des sanctions."
          },
          "pep_counterparty": {
            "type": "boolean",
            "description": "Exposition à une personne politiquement exposée. `null` lorsqu'aucun résultat PEP n'est disponible, ce qui est le cas de tous les résultats actuels car aucun fournisseur n'en signale ; `false` uniquement pour un résultat de filtrage explicitement négatif. Ne considérez pas `null` comme une vérification PEP terminée.",
            "nullable": true
          },
          "dominant_risk_category": {
            "type": "string",
            "nullable": true,
            "description": "Catégorie à haut risque ayant le poids le plus élevé, ou `null` si aucune n'est dominante (par exemple `sanctioned`, `mixer`, `stolen_funds`)."
          },
          "risk_factors": {
            "type": "array",
            "description": "Explication classée de `risk_score` : ce qui a produit ce verdict. Les fournisseurs évaluent une adresse selon leur propre modèle et ne renvoient qu'un verdict (Merkle Science renvoie un entier de 0 à 5), de sorte que le score seul n'est pas exploitable. Les éléments sont classés par niveau de risque décroissant, puis selon la valeur ayant transité par chaque facteur déterminant, plafonnés aux cinq plus importants ; `source_of_funds` et `destination_of_funds` contiennent toujours la ventilation complète. Un `risk_score` élevé sans entrée `is_high_risk` signifie que le fournisseur n'a signalé aucune correspondance avec des sanctions ou une entité attribuée et a évalué l'adresse uniquement d'après son propre modèle d'exposition - `summary` l'indique explicitement.",
            "items": {
              "type": "object",
              "properties": {
                "source": {
                  "type": "string",
                  "enum": [
                    "attribution",
                    "exposure"
                  ],
                  "description": "`attribution` correspond à ce que le fournisseur indique être l'adresse elle-même (son propre tag ou cluster) ; `exposure` indique où ses fonds ont réellement transité."
                },
                "category": {
                  "type": "string",
                  "description": "Catégorie de risque normalisée, même vocabulaire que la répartition de l'exposition."
                },
                "label": {
                  "type": "string",
                  "description": "La formulation propre au fournisseur pour le motif (par ex. `Gambling / Crypto only`), correspondant à ce que vous verriez également dans la console du fournisseur."
                },
                "entity_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Entité attribuée à l'origine du facteur, par exemple un site de jeux d'argent ou une plateforme d'échange."
                },
                "direction": {
                  "type": "string",
                  "enum": [
                    "incoming",
                    "outgoing",
                    "connected",
                    "unknown",
                    "attribution"
                  ],
                  "description": "Direction du flux de fonds, `attribution` lorsque le facteur déclenchant est l'étiquette propre à l'adresse, ou `unknown` lorsque le fournisseur n'a pas indiqué de direction."
                },
                "exposure_type": {
                  "type": "string",
                  "enum": [
                    "direct",
                    "indirect",
                    "unknown",
                    "attribution"
                  ],
                  "description": "`direct` (1 saut) ou `indirect` (multisauts), `attribution` pour le tag propre de l'adresse, ou `unknown` lorsque le fournisseur n'a pas indiqué à combien de sauts se trouve la contrepartie. Traitez `unknown` comme non classifié, et non comme `direct`."
                },
                "amount_usd": {
                  "type": "number",
                  "format": "float",
                  "nullable": true,
                  "description": "Valeur en USD attribuée à ce facteur."
                },
                "percentage": {
                  "type": "number",
                  "format": "float",
                  "description": "Part du volume TOTAL filtré de l'adresse, les deux sens combinés - contrairement au `percentage` dans `source_of_funds`/`destination_of_funds`, qui est normalisé par sens. Comparable et cumulable sur l'ensemble de la liste."
                },
                "is_high_risk": {
                  "type": "boolean",
                  "description": "Indique si la catégorie fait partie de celles que Didit considère comme à haut risque (`sanctioned`, `mixer`, `stolen_funds`, `ransomware`, `scam`, `darknet_market`, `terrorist_financing`, `child_exploitation`, `hacked_exchange`, `high_risk_exchange`, `seized_funds`)."
                },
                "description": {
                  "type": "string",
                  "description": "Rendu sur une seule ligne de l'élément déterminant, par ex. `9.01% indirect outgoing exposure to Gambling / Crypto only (Example Gambling)`."
                }
              }
            }
          },
          "raw_response": {
            "type": "object",
            "additionalProperties": true,
            "description": "Le payload propre au fournisseur. Sa structure est spécifique au fournisseur et peut changer sans préavis : lisez les champs normalisés plutôt que de le parser."
          },
          "report_signature": {
            "type": "string",
            "description": "Signature HMAC-SHA256 opaque sur ce résultat exact, restreinte à votre application. Non significative en elle-même — republiez l'intégralité du corps de la réponse, sans modification et en incluant ce champ, vers `POST /v3/wallet-screening/pdf/` pour en faire le rendu sous forme de PDF. L'endpoint PDF rejette la requête avec `400` si `report_signature` est manquant ou si un champ signé (par exemple `risk_score`, `severity`, `sanctions_hit`) a été modifié avant la republication."
          }
        },
        "required": [
          "provider",
          "screening_type",
          "risk_score",
          "severity",
          "status",
          "summary",
          "wallet_address",
          "blockchain",
          "sanctions_hit",
          "dominant_risk_category",
          "source_of_funds",
          "destination_of_funds",
          "counterparty_connections",
          "report_signature"
        ]
      },
      "NetworkRiskDisplay": {
        "type": "object",
        "properties": {
          "score": {
            "type": "integer",
            "description": "Score de risque, 0-100."
          },
          "band": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "description": "Catégorie dans laquelle le score s'affiche. high >= 70, medium >= 40, sinon low."
          },
          "bar": {
            "type": "number",
            "format": "float",
            "description": "Valeur normalisée de 0 à 1 pour afficher une barre de risque."
          }
        }
      },
      "NetworkNodeTag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true,
            "description": "Null pour les balises de garde, dont le token de couleur appartient au moteur de rendu."
          },
          "source": {
            "type": "string",
            "enum": [
              "subject_tag",
              "session_tag",
              "transaction_tag",
              "signal_guard"
            ],
            "description": "Origine du tag : un tag sur l'utilisateur/l'entreprise, un tag sur une session de ce réseau, un tag sur une transaction à laquelle appartient une partie, ou une condition de garde de signal (par ex. hub, IP de centre de données)."
          },
          "category": {
            "type": "string",
            "enum": [
              "customer",
              "quality"
            ],
            "nullable": true,
            "description": "customer pour les tags définis par le client, quality pour les tags de contrôle de la qualité du signal. Null lorsque non applicable."
          }
        }
      },
      "NetworkListItem": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "network_id": {
            "type": "string",
            "description": "Identifiant séquentiel par organisation lisible par l'utilisateur, par exemple N-0001."
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "in_review",
              "resolved",
              "dismissed"
            ],
            "description": "Statut du cycle de vie du réseau. Distinct de l'outcome_status par candidat au sein d'un réseau (approved/in_review/declined/not_completed)."
          },
          "risk": {
            "$ref": "#/components/schemas/NetworkRiskDisplay"
          },
          "pattern_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "exact_same_device",
                "similar_device",
                "same_ip_address",
                "same_address",
                "similar_selfie_backgrounds",
                "similar_poa_documents",
                "same_document_number",
                "same_phone_number",
                "same_email"
              ]
            },
            "description": "Les modèles de regroupement détectés dans ce réseau."
          },
          "signal_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "ip_address",
                "device",
                "face",
                "document_number",
                "phone",
                "email",
                "address"
              ]
            },
            "description": "Les types de signaux distincts présents dans ce réseau."
          },
          "member_counts": {
            "type": "object",
            "description": "Nombre de membres par catégorie (par ex. total, par outcome_status)."
          },
          "member_status": {
            "type": "object",
            "description": "Répartition des membres par outcome_status."
          },
          "signal_coverage": {
            "type": "object",
            "description": "Couverture par signal_type des membres de ce réseau."
          },
          "first_activity_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_activity_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "NetworkDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/NetworkListItem"
          },
          {
            "type": "object",
            "properties": {
              "stats": {
                "type": "object",
                "description": "Statistiques agrégées pour le réseau (par exemple totaux des membres)."
              },
              "fraud_tags": {
                "type": "array",
                "items": {
                  "type": "object"
                },
                "description": "Tags de schémas de fraude détectés sur le réseau."
              },
              "risk_signals": {
                "type": "object",
                "description": "Résumés des signaux de risque : residential_proxy_reuse, email_intelligence, phone_intelligence."
              },
              "reviewed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "reviewed_by": {
                "type": "string",
                "nullable": true
              },
              "review_reason": {
                "type": "string",
                "nullable": true
              }
            }
          }
        ],
        "properties": {
          "notes_count": {
            "type": "integer",
            "minimum": 0,
            "readOnly": true,
            "description": "Nombre de notes privées d'analyste dans cette enquête."
          }
        }
      },
      "NetworkGraphNode": {
        "type": "object",
        "description": "Un nœud sujet ou un nœud signal, différencié par kind. Les nœuds sujets (kind: vendor_user | vendor_business | transaction_party) comportent id, kind, subject, node_status (approved | in_review | declined | not_completed) et tags. Les nœuds signaux (kind: signal) comportent id, kind, uuid, signal_type, subject_count, coverage, is_hub, is_datacenter_ip, is_high_collision_device, node_status (signal_active | signal_guarded), tags, risk_evidence, first_seen_at et last_seen_at.",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "vendor_user",
              "vendor_business",
              "transaction_party",
              "signal"
            ]
          }
        }
      },
      "NetworkGraphEdge": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "source": {
            "type": "string",
            "description": "ID du nœud sujet."
          },
          "target": {
            "type": "string",
            "description": "ID du nœud de signal."
          },
          "subject_kind": {
            "type": "string",
            "enum": [
              "vendor_user",
              "vendor_business",
              "transaction_party"
            ]
          },
          "signal_type": {
            "type": "string",
            "enum": [
              "ip_address",
              "device",
              "face",
              "document_number",
              "phone",
              "email",
              "address"
            ]
          },
          "confidence": {
            "type": "number",
            "format": "float",
            "description": "1.0 pour une correspondance exacte."
          },
          "observation_count": {
            "type": "integer"
          },
          "first_seen_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_seen_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "NetworkGraph": {
        "type": "object",
        "properties": {
          "network": {
            "$ref": "#/components/schemas/NetworkDetail"
          },
          "depth": {
            "type": "integer",
            "nullable": true,
            "description": "Profondeur effective appliquée, ou null lorsqu'elle n'est pas restreinte (depth=all)."
          },
          "truncated": {
            "type": "boolean",
            "description": "Vrai si le voisinage a été tronqué par la profondeur."
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkGraphNode"
            }
          },
          "edges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkGraphEdge"
            }
          },
          "metrics": {
            "type": "object",
            "properties": {
              "node_count": {
                "type": "integer"
              },
              "edge_count": {
                "type": "integer"
              },
              "hub_signal_count": {
                "type": "integer"
              }
            }
          }
        }
      },
      "NetworkMember": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "object",
            "description": "Le vendor_user, vendor_business ou transaction_party représenté par ce membre."
          },
          "outcome_status": {
            "type": "string",
            "description": "Le résultat de la vérification/décision du sujet."
          },
          "node_status": {
            "type": "string",
            "enum": [
              "approved",
              "in_review",
              "declined",
              "not_completed",
              "signal_active",
              "signal_guarded"
            ],
            "description": "Pour une ligne de membre, il s'agit toujours de l'une des valeurs de résultat du sujet : approved, in_review, declined ou not_completed."
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkNodeTag"
            }
          },
          "risk": {
            "$ref": "#/components/schemas/NetworkRiskDisplay"
          },
          "signal_coverage": {
            "type": "object"
          },
          "shared_infrastructure": {
            "type": "object"
          },
          "joined_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_seen_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "provenance": {
            "type": "object",
            "properties": {
              "session_ids": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "business_session_ids": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "transaction_ids": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            }
          }
        }
      },
      "NetworkSignal": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "signal_type": {
            "type": "string",
            "enum": [
              "ip_address",
              "device",
              "face",
              "document_number",
              "phone",
              "email",
              "address"
            ]
          },
          "subject_count": {
            "type": "integer"
          },
          "coverage": {
            "type": "number",
            "format": "float"
          },
          "is_hub": {
            "type": "boolean",
            "description": "Vrai lorsque ce signal relie un nombre anormalement élevé de sujets."
          },
          "is_datacenter_ip": {
            "type": "boolean"
          },
          "is_high_collision_device": {
            "type": "boolean"
          },
          "node_status": {
            "type": "string",
            "enum": [
              "signal_active",
              "signal_guarded"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkNodeTag"
            }
          },
          "risk_evidence": {
            "type": "object"
          },
          "first_seen_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_seen_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "NetworkTimelineEvent": {
        "type": "object",
        "properties": {
          "event_type": {
            "type": "string",
            "description": "par exemple network_detected, signal_observed, network_in_review, network_resolved, network_dismissed."
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "label": {
            "type": "string"
          },
          "metadata": {
            "type": "object"
          }
        }
      },
      "NetworkMap": {
        "type": "object",
        "properties": {
          "network": {
            "$ref": "#/components/schemas/NetworkDetail"
          },
          "convergence_count": {
            "type": "integer",
            "description": "Nombre de points d'adresse/localisation distincts vers lesquels convergent les membres."
          },
          "countries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "points": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "country": {
                  "type": "string",
                  "nullable": true
                },
                "country_code": {
                  "type": "string",
                  "nullable": true
                },
                "city": {
                  "type": "string",
                  "nullable": true
                },
                "latitude": {
                  "type": "number",
                  "format": "float",
                  "nullable": true
                },
                "longitude": {
                  "type": "number",
                  "format": "float",
                  "nullable": true
                },
                "observed_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                }
              }
            }
          }
        }
      },
      "EntityNetworkMembership": {
        "type": "object",
        "properties": {
          "network": {
            "$ref": "#/components/schemas/NetworkListItem"
          },
          "subject": {
            "type": "object"
          },
          "signal_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "ip_address",
                "device",
                "face",
                "document_number",
                "phone",
                "email",
                "address"
              ]
            }
          },
          "signal_count": {
            "type": "integer"
          },
          "joined_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_seen_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "RiskSignals": {
        "type": "object",
        "description": "Contexte d'appareil et de réseau optionnel observé par votre application. Tous les champs sont optionnels. Les renseigner alimente la détection de correspondance inter-sessions dans Networks.",
        "properties": {
          "ip": {
            "type": "string",
            "format": "ip",
            "description": "Adresse IPv4 ou IPv6 observée pour l'utilisateur final.",
            "example": "192.0.2.1"
          },
          "device_id": {
            "type": "string",
            "maxLength": 255,
            "description": "Identifiant stable de l'appareil collecté par votre application (Android `ANDROID_ID`, iOS `identifierForVendor`)."
          },
          "device_platform": {
            "type": "string",
            "enum": [
              "android",
              "ios",
              "ipados",
              "tvos",
              "web"
            ],
            "description": "Plateforme de l'appareil de l'utilisateur final."
          },
          "device_model": {
            "type": "string",
            "maxLength": 255,
            "description": "Modèle d'appareil signalé par votre application."
          },
          "os_version": {
            "type": "string",
            "maxLength": 64,
            "description": "Version du système d'exploitation."
          },
          "app_version": {
            "type": "string",
            "maxLength": 64,
            "description": "Version de votre application."
          },
          "user_agent": {
            "type": "string",
            "maxLength": 512,
            "description": "Agent utilisateur du navigateur ou de l'application."
          }
        }
      },
      "PhoneRiskRequest": {
        "type": "object",
        "required": [
          "phone_number"
        ],
        "properties": {
          "phone_number": {
            "type": "string",
            "maxLength": 20,
            "description": "Numéro de téléphone à évaluer. Il est validé et normalisé au format E.164.",
            "example": "+14155552671"
          },
          "country_code": {
            "type": "string",
            "maxLength": 3,
            "description": "Indication de pays ISO 3166-1 alpha-2 ou alpha-3 optionnelle pour la couverture du renseignement.",
            "example": "US"
          },
          "signals": {
            "$ref": "#/components/schemas/RiskSignals"
          },
          "vendor_data": {
            "type": "string",
            "description": "Votre référence stable pour cette requête. Enregistrée sur la session API et renvoyée dans la réponse."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Vos métadonnées JSON non sensibles. Enregistrées sur la session d'API et renvoyées dans la réponse."
          },
          "enable_social": {
            "type": "boolean",
            "default": false,
            "description": "Si true, recherche également l'empreinte sociale du numéro : les plateformes de messagerie, sociales, d'e-commerce et professionnelles sur lesquelles il est enregistré. Facturé comme une unité `phone_social` par requête en plus du prix propre de cet endpoint.",
            "example": true
          }
        }
      },
      "EmailRiskRequest": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Adresse e-mail à évaluer.",
            "example": "alice@example.com"
          },
          "country_code": {
            "type": "string",
            "maxLength": 3,
            "description": "Indication de pays ISO 3166-1 alpha-2 ou alpha-3 optionnelle pour la couverture du renseignement.",
            "example": "US"
          },
          "signals": {
            "$ref": "#/components/schemas/RiskSignals"
          },
          "vendor_data": {
            "type": "string",
            "description": "Votre référence stable pour cette requête. Enregistrée sur la session API et renvoyée dans la réponse."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Vos métadonnées JSON non sensibles. Enregistrées sur la session d'API et renvoyées dans la réponse."
          },
          "enable_social": {
            "type": "boolean",
            "default": false,
            "description": "Si true, recherche également l'empreinte sociale de l'adresse : les plateformes d'e-mail, sociales, professionnelles, d'e-commerce et de divertissement sur lesquelles elle est enregistrée. Facturé comme une unité `email_social` par requête en plus du prix propre à cet endpoint.",
            "example": true
          }
        }
      },
      "IPRiskRequest": {
        "type": "object",
        "required": [
          "ip_address"
        ],
        "properties": {
          "ip_address": {
            "type": "string",
            "format": "ip",
            "description": "Adresse IPv4 ou IPv6 à évaluer.",
            "example": "8.8.8.8"
          },
          "claimed_country": {
            "type": "string",
            "maxLength": 3,
            "description": "Pays ISO 3166-1 alpha-2 ou alpha-3 optionnel déclaré par l'utilisateur ou la session. Utilisé pour calculer `country_mismatch`.",
            "example": "ESP"
          },
          "user_agent": {
            "type": "string",
            "maxLength": 512,
            "description": "Agent utilisateur observé par votre backend. Enregistré comme contexte de requête ; il ne fournit pas d'empreinte d'appareil."
          },
          "vendor_data": {
            "type": "string",
            "description": "Votre référence stable pour cette requête. Enregistrée sur la session API et renvoyée dans la réponse."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Vos métadonnées JSON non sensibles. Enregistrées sur la session d'API et renvoyées dans la réponse."
          }
        }
      },
      "RiskWarning": {
        "type": "object",
        "required": [
          "feature",
          "risk",
          "log_type",
          "short_description",
          "long_description"
        ],
        "properties": {
          "feature": {
            "type": "string",
            "description": "Fonctionnalité ayant généré l'avertissement."
          },
          "risk": {
            "type": "string",
            "description": "Code de risque lisible par machine. De nouvelles valeurs peuvent être ajoutées au fil du temps."
          },
          "additional_data": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Contexte spécifique au risque, ou `null`."
          },
          "log_type": {
            "type": "string",
            "enum": [
              "error",
              "warning",
              "information"
            ],
            "description": "Gravité utilisée par les règles de décision."
          },
          "short_description": {
            "type": "string",
            "description": "Résumé en une ligne lisible par l'utilisateur."
          },
          "long_description": {
            "type": "string",
            "description": "Explication lisible par l'humain."
          }
        }
      },
      "RiskLifecycleEvent": {
        "type": "object",
        "required": [
          "type",
          "timestamp",
          "details",
          "fee"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Type d'événement lisible par machine. De nouvelles valeurs peuvent être ajoutées au fil du temps."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure de l'événement."
          },
          "details": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Payload spécifique à l'événement, ou `null`."
          },
          "fee": {
            "type": "number",
            "description": "Montant en USD facturé pour cet événement."
          }
        }
      },
      "PhoneMatchItem": {
        "type": "object",
        "description": "Une autre session de votre application qui a utilisé le même numéro de téléphone avec un `vendor_data` différent.",
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de session de l'autre vérification ayant utilisé ce numéro de téléphone."
          },
          "session_number": {
            "type": "integer",
            "description": "Numéro séquentiel lisible par l'humain de cette session."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "`vendor_data` de cette session."
          },
          "verification_date": {
            "type": "string",
            "description": "Date et heure de création de cette session (`YYYY-MM-DDTHH:MM:SSZ`)."
          },
          "phone_number": {
            "type": "string",
            "description": "Le numéro de téléphone correspondant."
          },
          "status": {
            "type": "string",
            "description": "Statut de cette session (par exemple, `Approved`, `Declined`, `In Progress`)."
          },
          "is_blocklisted": {
            "type": "boolean",
            "description": "Indique si le numéro de téléphone figure sur la liste de blocage de votre application."
          },
          "api_service": {
            "type": "string",
            "nullable": true,
            "description": "Pour les sessions de type API, l'API autonome qui l'a créée ; `null` pour les sessions de vérification régulières."
          },
          "source": {
            "type": "string",
            "description": "Emplacement où la correspondance a été trouvée. Généralement `session` ; une correspondance avec une liste de blocage via une entrée de liste d'organisation utilise `list_entry`."
          }
        }
      },
      "EmailMatchItem": {
        "type": "object",
        "description": "Une autre session de votre application qui a utilisé la même adresse e-mail avec un `vendor_data` différent.",
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de session de l'autre vérification ayant utilisé cette adresse e-mail."
          },
          "session_number": {
            "type": "integer",
            "description": "Numéro séquentiel lisible par l'humain de cette session."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "`vendor_data` de cette session."
          },
          "verification_date": {
            "type": "string",
            "description": "Date et heure de création de cette session (`YYYY-MM-DDTHH:MM:SSZ`)."
          },
          "email": {
            "type": "string",
            "description": "L'adresse e-mail correspondante."
          },
          "status": {
            "type": "string",
            "description": "Statut de cette session (par exemple, `Approved`, `Declined`, `In Progress`)."
          },
          "is_blocklisted": {
            "type": "boolean",
            "description": "Indique si l'adresse e-mail figure sur la liste de blocage de votre application."
          },
          "api_service": {
            "type": "string",
            "nullable": true,
            "description": "Pour les sessions de type API, l'API autonome qui l'a créée ; `null` pour les sessions de vérification régulières."
          },
          "source": {
            "type": "string",
            "description": "Emplacement où la correspondance a été trouvée. Généralement `session` ; une correspondance avec une liste de blocage via une entrée de liste d'organisation utilise `list_entry`."
          }
        }
      },
      "PhoneIntelligence": {
        "type": "object",
        "description": "Bloc de renseignements téléphoniques normalisé. Présent uniquement lorsque le module complémentaire d'intelligence a été exécuté pour cette recherche ; lorsqu'il est présent, il est également exposé sous l'alias `enrichment` avec des valeurs identiques.",
        "properties": {
          "score": {
            "type": "number",
            "nullable": true,
            "description": "Score de risque normalisé de 0 à 100. Plus la valeur est élevée, plus le risque est grand."
          },
          "phone_type_risk": {
            "type": "string",
            "nullable": true,
            "description": "`Low`, `Medium` ou `High`, dérivé du score."
          },
          "phone_trust_index": {
            "type": "number",
            "nullable": true,
            "description": "Inverse du score, pour les tableaux de bord qui préfèrent qu'une valeur plus élevée soit meilleure."
          },
          "network_stability_index": {
            "type": "number",
            "nullable": true,
            "description": "Stabilité du réseau de la ligne."
          },
          "is_disposable": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque le numéro semble jetable ou virtuel."
          },
          "is_ported": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque le numéro a changé d'opérateur."
          },
          "is_recently_ported": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque la portabilité a eu lieu récemment."
          },
          "carrier_type": {
            "type": "string",
            "nullable": true,
            "description": "Classification de la ligne signalée par la recherche (par exemple, `mobile`)."
          },
          "reason_codes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "description": "Identifiant Didit stable du signal, par exemple `IR-5AC67A32`. Opaque : utilisez-le pour regrouper et filtrer, ne l'interprétez pas."
                },
                "value": {
                  "nullable": true,
                  "description": "Pour un indicateur de risque (par exemple `voip`, `leaked`, `disposable`, `spam_trap`), sa valeur : un booléen, un niveau ou une date. Null pour un code de motif noté."
                },
                "direction": {
                  "type": "string",
                  "enum": [
                    "risk",
                    "trust"
                  ],
                  "description": "Indique si le signal a augmenté le risque ou renforcé la confiance."
                },
                "message": {
                  "type": "string",
                  "description": "Explication lisible par l'humain du signal, en anglais."
                },
                "impact_level": {
                  "type": "string",
                  "nullable": true,
                  "description": "Mesure dans laquelle le signal a influencé le score, par exemple `low`, `medium` ou `high`."
                }
              }
            },
            "description": "Signaux expliquant le score, chacun accompagné d'un code Didit stable, d'un sens, d'un message et d'un niveau d'impact. De nouveaux codes pouvant apparaître au fil du temps, ne rejetez pas les codes inconnus."
          }
        }
      },
      "EmailIntelligence": {
        "type": "object",
        "description": "Bloc de renseignements d'e-mail normalisé. Présent uniquement lorsque le module complémentaire d'intelligence a été exécuté pour cet e-mail ; lorsqu'il est présent, il est également exposé sous l'alias `enrichment` avec des valeurs identiques.",
        "properties": {
          "score": {
            "type": "number",
            "nullable": true,
            "description": "Score de risque normalisé de 0 à 100. Plus la valeur est élevée, plus le risque est grand."
          },
          "deliverable": {
            "type": "string",
            "nullable": true,
            "description": "Tranche de délivrabilité (par ex., `high`)."
          },
          "breach_risk_level": {
            "type": "string",
            "nullable": true,
            "description": "`Low`, `Medium` ou `High`."
          },
          "breach_risk_index": {
            "type": "number",
            "nullable": true,
            "description": "Indice numérique de risque de violation."
          },
          "is_recent_breach": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque l'adresse apparaît dans une violation récente de données."
          },
          "is_frequent_breached": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque l'adresse apparaît dans de nombreuses violations de données."
          },
          "is_disposable": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque le domaine appartient à un fournisseur d'e-mails jetables."
          },
          "is_free_domain": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque le domaine provient d'un fournisseur d'e-mails gratuit."
          },
          "is_breached": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque l'adresse apparaît dans des violations de données connues."
          },
          "no_of_breaches": {
            "type": "number",
            "nullable": true,
            "description": "Nombre de violations de données connues contenant l'adresse."
          },
          "reason_codes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "description": "Identifiant Didit stable du signal, par exemple `IR-5AC67A32`. Opaque : utilisez-le pour regrouper et filtrer, ne l'interprétez pas."
                },
                "value": {
                  "nullable": true,
                  "description": "Pour un indicateur de risque (par exemple `voip`, `leaked`, `disposable`, `spam_trap`), sa valeur : un booléen, un niveau ou une date. Null pour un code de motif noté."
                },
                "direction": {
                  "type": "string",
                  "enum": [
                    "risk",
                    "trust"
                  ],
                  "description": "Indique si le signal a augmenté le risque ou renforcé la confiance."
                },
                "message": {
                  "type": "string",
                  "description": "Explication lisible par l'humain du signal, en anglais."
                },
                "impact_level": {
                  "type": "string",
                  "nullable": true,
                  "description": "Mesure dans laquelle le signal a influencé le score, par exemple `low`, `medium` ou `high`."
                }
              }
            },
            "description": "Signaux expliquant le score, chacun accompagné d'un code Didit stable, d'un sens, d'un message et d'un niveau d'impact. De nouveaux codes pouvant apparaître au fil du temps, ne rejetez pas les codes inconnus."
          }
        }
      },
      "IPRiskResult": {
        "type": "object",
        "description": "Résultat du risque IP. Les champs d'enrichissement individuels peuvent être `null` lorsque la recherche n'a renvoyé aucune donnée exploitable.",
        "required": [
          "status",
          "threat"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "Approved",
              "In Review"
            ],
            "description": "`In Review` lorsque le pays résolu est en conflit avec `claimed_country`, ou lorsque l'adresse est associée à une infrastructure VPN, Tor ou de centre de données. Sinon `Approved`."
          },
          "ip_address": {
            "type": "string",
            "nullable": true,
            "description": "L'adresse notée. `null` si aucune source d'enrichissement n'a renvoyé de données exploitables."
          },
          "ip_country": {
            "type": "string",
            "nullable": true,
            "description": "Nom du pays résolu."
          },
          "ip_country_code": {
            "type": "string",
            "nullable": true,
            "description": "Code pays résolu. Comparez les pays via `country_mismatch` au lieu de comparer vous-même les chaînes de pays brutes."
          },
          "ip_state": {
            "type": "string",
            "nullable": true,
            "description": "État ou région résolu."
          },
          "ip_city": {
            "type": "string",
            "nullable": true,
            "description": "Ville résolue."
          },
          "latitude": {
            "type": "number",
            "nullable": true,
            "description": "Géolocalisation réseau approximative, et non une localisation précise de l'appareil."
          },
          "longitude": {
            "type": "number",
            "nullable": true,
            "description": "Géolocalisation réseau approximative, et non une localisation précise de l'appareil."
          },
          "isp": {
            "type": "string",
            "nullable": true,
            "description": "Fournisseur d'accès à Internet desservant l'adresse."
          },
          "organization": {
            "type": "string",
            "nullable": true,
            "description": "Organisation propriétaire du bloc d'adresses."
          },
          "is_vpn_or_tor": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque l'adresse est associée à une infrastructure VPN ou Tor."
          },
          "is_data_center": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque l'adresse appartient à un réseau d'hébergement ou de centre de données."
          },
          "time_zone": {
            "type": "string",
            "nullable": true,
            "description": "Fuseau horaire de la localisation résolue."
          },
          "time_zone_offset": {
            "type": "string",
            "nullable": true,
            "description": "Décalage UTC de l'emplacement résolu."
          },
          "asn_number": {
            "type": "number",
            "nullable": true,
            "description": "Numéro de système autonome."
          },
          "asn_organization": {
            "type": "string",
            "nullable": true,
            "description": "Organisation exploitant le système autonome."
          },
          "connection_type": {
            "type": "string",
            "nullable": true,
            "description": "Classification de la connexion (par ex., `cellular`, `hosting`)."
          },
          "carrier": {
            "type": "string",
            "nullable": true,
            "description": "Opérateur mobile lorsque l'adresse est sur un réseau mobile."
          },
          "proxy_type": {
            "type": "string",
            "nullable": true,
            "description": "Classification du proxy lorsque l'adresse se trouve derrière un proxy."
          },
          "claimed_country": {
            "type": "string",
            "nullable": true,
            "description": "Écho du `claimed_country` que vous avez envoyé."
          },
          "country_mismatch": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque le pays résolu diffère de `claimed_country`. `null` lorsqu'aucune donnée d'enrichissement ou aucun pays revendiqué n'est disponible."
          },
          "threat": {
            "type": "object",
            "additionalProperties": true,
            "description": "Preuves de menaces réseau au format libre issues de la source d'enrichissement (par ex. `is_proxy`, `is_tor`). Objet vide lorsqu'aucune donnée d'enrichissement n'est disponible. À traiter comme un détail de diagnostic, et non comme un contrat stable."
          }
        }
      },
      "PhoneRiskResponse": {
        "type": "object",
        "required": [
          "request_id",
          "status",
          "created_at"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de la session d'API créée pour cette requête. Enregistrez-le avec `vendor_data` si vous devez faire correspondre le résultat avec des webhooks ultérieurs ou l'activité de la console."
          },
          "status": {
            "type": "string",
            "enum": [
              "Approved",
              "In Review",
              "Declined"
            ],
            "description": "Décision finale pour cette session d'API. Habituellement `Approved` ; l'évaluation des risques peut donner `In Review` ou `Declined`."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Écho des `vendor_data` que vous avez envoyées, `null` si vous n'en avez pas envoyé."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Écho des `metadata` que vous avez envoyées, `null` si vous n'en avez pas envoyé."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cette réponse."
          },
          "phone": {
            "type": "object",
            "description": "Rapport de téléphone normalisé, le même bloc que celui utilisé par les réponses de Vérification du téléphone.",
            "required": [
              "status"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "Approved",
                  "In Review",
                  "Declined"
                ],
                "description": "Décision pour ce numéro de téléphone. Reflète le `status` de premier niveau."
              },
              "phone_number_prefix": {
                "type": "string",
                "description": "Indicatif téléphonique du pays avec un `+` au début (par ex., `+1`).",
                "example": "+1"
              },
              "phone_number": {
                "type": "string",
                "description": "Numéro national sans l'indicatif téléphonique du pays.",
                "example": "4155552671"
              },
              "full_number": {
                "type": "string",
                "description": "Numéro complet au format E.164.",
                "example": "+14155552671"
              },
              "country_code": {
                "type": "string",
                "nullable": true,
                "description": "Pays ISO 3166-1 alpha-2 du numéro.",
                "example": "US"
              },
              "country_name": {
                "type": "string",
                "description": "Nom complet du pays dérivé de `country_code`.",
                "example": "United States"
              },
              "carrier": {
                "type": "object",
                "nullable": true,
                "description": "Réseau actuel desservant le numéro. `null` lorsque la recherche n'a pas pu identifier d'opérateur.",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nom de l'opérateur. Chaîne vide lorsque la recherche n'a pas pu l'identifier."
                  },
                  "type": {
                    "type": "string",
                    "description": "Type de ligne signalé par la recherche : `mobile`, `fixed_line`, `voip`, `isp`, `vpn`, `toll_free`, `premium_rate` ou similaire."
                  }
                }
              },
              "is_disposable": {
                "type": "boolean",
                "description": "`true` lorsque le numéro appartient à un service de numéros temporaires ou jetables."
              },
              "is_virtual": {
                "type": "boolean",
                "description": "`true` lorsque le type de ligne est virtuel (`voip`, `isp` ou `vpn`)."
              },
              "verification_method": {
                "type": "string",
                "nullable": true,
                "description": "Canal OTP de la vérification sous-jacente. `null` pour les recherches de risque, qui n'envoient jamais de code."
              },
              "verification_attempts": {
                "type": "integer",
                "description": "Envois d'OTP pour ce numéro. `0` pour les recherches de risque."
              },
              "verified_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Moment où le numéro a été vérifié pour la dernière fois par un OTP. `null` pour les recherches de risque."
              },
              "warnings": {
                "type": "array",
                "description": "Avertissements de risque enregistrés pour cette requête. Tableau vide lorsqu'il n'y en a aucun.",
                "items": {
                  "$ref": "#/components/schemas/RiskWarning"
                }
              },
              "lifecycle": {
                "type": "array",
                "description": "Piste d'audit chronologique de la requête. Tableau vide pour les recherches de risque sans événements d'envoi.",
                "items": {
                  "$ref": "#/components/schemas/RiskLifecycleEvent"
                }
              },
              "matches": {
                "type": "array",
                "description": "Autres sessions de votre application où le même numéro de téléphone a été utilisé par un utilisateur différent (`vendor_data` différent). Jusqu'à 5 entrées. Tableau vide lorsqu'il n'y a aucune correspondance.",
                "items": {
                  "$ref": "#/components/schemas/PhoneMatchItem"
                }
              },
              "phone_intelligence": {
                "$ref": "#/components/schemas/PhoneIntelligence"
              },
              "enrichment": {
                "$ref": "#/components/schemas/PhoneIntelligence"
              },
              "phone_social": {
                "$ref": "#/components/schemas/PhoneSocialFootprint"
              }
            }
          }
        }
      },
      "EmailRiskResponse": {
        "type": "object",
        "required": [
          "request_id",
          "status",
          "created_at"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de la session d'API créée pour cette requête. Enregistrez-le avec `vendor_data` si vous devez faire correspondre le résultat avec des webhooks ultérieurs ou l'activité de la console."
          },
          "status": {
            "type": "string",
            "enum": [
              "Approved",
              "In Review",
              "Declined"
            ],
            "description": "Décision finale pour cette session d'API. Habituellement `Approved` ; l'évaluation des risques peut donner `In Review` ou `Declined`."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Écho des `vendor_data` que vous avez envoyées, `null` si vous n'en avez pas envoyé."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Écho des `metadata` que vous avez envoyées, `null` si vous n'en avez pas envoyé."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cette réponse."
          },
          "email": {
            "type": "object",
            "description": "Rapport d'e-mail normalisé, le même bloc que celui utilisé par les réponses de Vérification de l'e-mail.",
            "required": [
              "status",
              "email",
              "is_breached",
              "breaches",
              "is_disposable",
              "is_undeliverable"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "Approved",
                  "In Review",
                  "Declined"
                ],
                "description": "Décision pour cette adresse e-mail. Reflète le `status` de premier niveau."
              },
              "email": {
                "type": "string",
                "description": "L'adresse notée.",
                "example": "alice@example.com"
              },
              "is_breached": {
                "type": "boolean",
                "description": "Indique si l'adresse apparaît dans une fuite connue d'identifiants."
              },
              "breaches": {
                "type": "array",
                "description": "Jusqu'aux 5 fuites de données connues les plus récentes contenant cette adresse. Tableau vide lorsque `is_breached` vaut `false`.",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Identifiant de la violation."
                    },
                    "domain": {
                      "type": "string",
                      "description": "Domaine du service compromis."
                    },
                    "breach_date": {
                      "type": "string",
                      "format": "date",
                      "description": "Date à laquelle la violation s'est produite."
                    },
                    "breach_emails_count": {
                      "type": "integer",
                      "description": "Nombre total de comptes exposés lors de la violation."
                    },
                    "description": {
                      "type": "string",
                      "description": "Description lisible par l'humain de la violation (peut contenir du balisage HTML)."
                    },
                    "logo_path": {
                      "type": "string",
                      "description": "URL du logo du service compromis."
                    },
                    "data_classes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Catégories de données exposées, en snake_case (par exemple, `email_addresses`, `passwords`)."
                    },
                    "is_verified": {
                      "type": "boolean",
                      "description": "Indique si la légitimité de la fuite a été vérifiée."
                    }
                  }
                }
              },
              "is_disposable": {
                "type": "boolean",
                "description": "Indique si le domaine appartient à un fournisseur d'adresses e-mail temporaires."
              },
              "is_undeliverable": {
                "type": "boolean",
                "description": "Indique si l'adresse s'est révélée non distribuable."
              },
              "verification_attempts": {
                "type": "integer",
                "description": "Envois d'OTP pour cette adresse. `0` pour les recherches de risque."
              },
              "verified_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure de la dernière vérification de l'adresse par un code à usage unique (OTP). `null` pour les recherches de risque."
              },
              "warnings": {
                "type": "array",
                "description": "Avertissements de risque enregistrés pour cette requête. Tableau vide lorsqu'il n'y en a aucun.",
                "items": {
                  "$ref": "#/components/schemas/RiskWarning"
                }
              },
              "lifecycle": {
                "type": "array",
                "description": "Piste d'audit chronologique de la requête. Tableau vide pour les recherches de risque sans envois.",
                "items": {
                  "$ref": "#/components/schemas/RiskLifecycleEvent"
                }
              },
              "matches": {
                "type": "array",
                "description": "Autres sessions de votre application où la même adresse e-mail a été utilisée par un utilisateur différent (`vendor_data` différent). Jusqu'à 5 entrées. Tableau vide lorsqu'il n'y a aucune correspondance.",
                "items": {
                  "$ref": "#/components/schemas/EmailMatchItem"
                }
              },
              "email_intelligence": {
                "$ref": "#/components/schemas/EmailIntelligence"
              },
              "enrichment": {
                "$ref": "#/components/schemas/EmailIntelligence"
              },
              "email_social": {
                "$ref": "#/components/schemas/EmailSocialFootprint"
              }
            }
          }
        }
      },
      "IPRiskResponse": {
        "type": "object",
        "required": [
          "request_id",
          "status",
          "created_at"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de la session d'API créée pour cette requête. Enregistrez-le avec `vendor_data` si vous devez faire correspondre le résultat avec des webhooks ultérieurs ou l'activité de la console."
          },
          "status": {
            "type": "string",
            "enum": [
              "Approved",
              "In Review"
            ],
            "description": "Décision pour cette session d'API : `In Review` en cas de risque lié au réseau ou de discordance de pays, sinon `Approved`."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Écho des `vendor_data` que vous avez envoyées, `null` si vous n'en avez pas envoyé."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Écho des `metadata` que vous avez envoyées, `null` si vous n'en avez pas envoyé."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cette réponse."
          },
          "ip": {
            "type": "object",
            "description": "Résultat du risque IP. Les champs d'enrichissement individuels peuvent être `null` lorsque la recherche n'a renvoyé aucune donnée exploitable.",
            "required": [
              "status",
              "threat"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "Approved",
                  "In Review"
                ],
                "description": "`In Review` lorsque le pays résolu est en conflit avec `claimed_country`, ou lorsque l'adresse est associée à une infrastructure VPN, Tor ou de centre de données. Sinon `Approved`."
              },
              "ip_address": {
                "type": "string",
                "nullable": true,
                "description": "L'adresse notée. `null` si aucune source d'enrichissement n'a renvoyé de données exploitables."
              },
              "ip_country": {
                "type": "string",
                "nullable": true,
                "description": "Nom du pays résolu."
              },
              "ip_country_code": {
                "type": "string",
                "nullable": true,
                "description": "Code pays résolu. Comparez les pays via `country_mismatch` au lieu de comparer vous-même les chaînes de pays brutes."
              },
              "ip_state": {
                "type": "string",
                "nullable": true,
                "description": "État ou région résolu."
              },
              "ip_city": {
                "type": "string",
                "nullable": true,
                "description": "Ville résolue."
              },
              "latitude": {
                "type": "number",
                "nullable": true,
                "description": "Géolocalisation réseau approximative, et non une localisation précise de l'appareil."
              },
              "longitude": {
                "type": "number",
                "nullable": true,
                "description": "Géolocalisation réseau approximative, et non une localisation précise de l'appareil."
              },
              "isp": {
                "type": "string",
                "nullable": true,
                "description": "Fournisseur d'accès à Internet desservant l'adresse."
              },
              "organization": {
                "type": "string",
                "nullable": true,
                "description": "Organisation propriétaire du bloc d'adresses."
              },
              "is_vpn_or_tor": {
                "type": "boolean",
                "nullable": true,
                "description": "`true` lorsque l'adresse est associée à une infrastructure VPN ou Tor."
              },
              "is_data_center": {
                "type": "boolean",
                "nullable": true,
                "description": "`true` lorsque l'adresse appartient à un réseau d'hébergement ou de centre de données."
              },
              "time_zone": {
                "type": "string",
                "nullable": true,
                "description": "Fuseau horaire de la localisation résolue."
              },
              "time_zone_offset": {
                "type": "string",
                "nullable": true,
                "description": "Décalage UTC de l'emplacement résolu."
              },
              "asn_number": {
                "type": "number",
                "nullable": true,
                "description": "Numéro de système autonome."
              },
              "asn_organization": {
                "type": "string",
                "nullable": true,
                "description": "Organisation exploitant le système autonome."
              },
              "connection_type": {
                "type": "string",
                "nullable": true,
                "description": "Classification de la connexion (par ex., `cellular`, `hosting`)."
              },
              "carrier": {
                "type": "string",
                "nullable": true,
                "description": "Opérateur mobile lorsque l'adresse est sur un réseau mobile."
              },
              "proxy_type": {
                "type": "string",
                "nullable": true,
                "description": "Classification du proxy lorsque l'adresse se trouve derrière un proxy."
              },
              "claimed_country": {
                "type": "string",
                "nullable": true,
                "description": "Écho du `claimed_country` que vous avez envoyé."
              },
              "country_mismatch": {
                "type": "boolean",
                "nullable": true,
                "description": "`true` lorsque le pays résolu diffère de `claimed_country`. `null` lorsqu'aucune donnée d'enrichissement ou aucun pays revendiqué n'est disponible."
              },
              "threat": {
                "type": "object",
                "additionalProperties": true,
                "description": "Preuves de menaces réseau au format libre issues de la source d'enrichissement (par ex. `is_proxy`, `is_tor`). Objet vide lorsqu'aucune donnée d'enrichissement n'est disponible. À traiter comme un détail de diagnostic, et non comme un contrat stable."
              }
            }
          }
        }
      },
      "SocialFootprintPlatform": {
        "type": "object",
        "properties": {
          "platform": {
            "type": "string",
            "description": "Identifiant de plateforme.",
            "example": "whatsapp"
          },
          "category": {
            "type": "string",
            "description": "Catégorie de plateforme, par ex. MESSAGING, SOCIAL_MEDIA, ECOMMERCE, PROFESSIONAL, EMAIL_PROVIDER.",
            "example": "MESSAGING"
          },
          "scope": {
            "type": "string",
            "enum": [
              "global",
              "local"
            ],
            "description": "`global` pour les plateformes mondiales, `local` pour celles spécifiques à une région.",
            "example": "global"
          }
        }
      },
      "SocialFootprintCategorySummary": {
        "type": "object",
        "properties": {
          "registered": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes de cette catégorie pour lesquelles l'inscription est confirmée.",
            "example": 2
          },
          "ratio": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "description": "Part des plateformes vérifiées de la catégorie comportant une inscription, de 0.0 à 1.0.",
            "example": 0.6667
          }
        }
      },
      "SocialFootprintProfile": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nom du profil, lorsque la plateforme en fournit un."
          },
          "photo": {
            "type": "string",
            "nullable": true,
            "description": "URL de la photo de profil, lorsque la plateforme en fournit une."
          },
          "about": {
            "type": "string",
            "nullable": true,
            "description": "Texte de présentation/biographie du profil, lorsque la plateforme en fournit un."
          },
          "privacy_status": {
            "type": "string",
            "nullable": true,
            "enum": [
              "PUBLIC",
              "PRIVATE",
              null
            ],
            "description": "Visibilité du profil, lorsque la plateforme la fournit."
          },
          "business_account": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si le profil est un compte professionnel, lorsque la plateforme l'expose."
          }
        }
      },
      "PhoneSocialFootprint": {
        "type": "object",
        "nullable": true,
        "description": "Empreinte sociale du numéro de téléphone : les plateformes en ligne sur lesquelles il est enregistré. Présent uniquement lorsque `enable_social` a été défini et que la vérification s'est terminée. Chaque décompte peut être nul lorsqu'aucune donnée n'a été renvoyée pour celui-ci. `profiles_registered: 0` signifie que les plateformes ont été vérifiées et que le numéro de téléphone n'a été trouvé sur aucune d'entre elles, une réponse valide et facturable, ainsi qu'un signal fréquent d'identité synthétique.",
        "properties": {
          "profiles_registered": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes pour lesquelles l'inscription du numéro de téléphone est confirmée.",
            "example": 5
          },
          "profiles_checked": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes évaluées pour l'inscription.",
            "example": 14
          },
          "names_found": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes ayant renvoyé un nom associé.",
            "example": 0
          },
          "photos_found": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes ayant renvoyé une photo de profil.",
            "example": 0
          },
          "communication_breadth": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes de communication sur lesquelles une présence a été détectée.",
            "example": 2
          },
          "digital_footprint_diversity": {
            "type": "integer",
            "nullable": true,
            "description": "Catégories de plateformes distinctes avec une présence détectée.",
            "example": 5
          },
          "digital_sophistication_index": {
            "type": "integer",
            "nullable": true,
            "description": "Indicateur composite de maturité numérique, de 0 à 10.",
            "example": 5
          },
          "engagement_depth_index": {
            "type": "integer",
            "nullable": true,
            "description": "Indicateur de richesse du profil, de 0 à 10.",
            "example": 3
          },
          "subscription_affordability_index": {
            "type": "integer",
            "nullable": true,
            "description": "Mix de plateformes gratuites vs payantes, 0-10.",
            "example": 2
          },
          "free_platforms": {
            "type": "integer",
            "nullable": true,
            "description": "Inscriptions sur des plateformes gratuites.",
            "example": 4
          },
          "full_paid_platforms": {
            "type": "integer",
            "nullable": true,
            "description": "Inscriptions sur des plateformes payantes.",
            "example": 0
          },
          "partial_paid_platforms": {
            "type": "integer",
            "nullable": true,
            "description": "Inscriptions sur des plateformes freemium.",
            "example": 1
          },
          "whatsapp_profile_completeness": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Basic",
              "Partial",
              "Complete",
              "Not Present",
              null
            ],
            "description": "Niveau de complétion du profil WhatsApp. Téléphone uniquement ; null pour l'e-mail.",
            "example": "Partial"
          },
          "registered_platforms": {
            "type": "array",
            "description": "Plateformes pour lesquelles l'inscription est confirmée.",
            "items": {
              "$ref": "#/components/schemas/SocialFootprintPlatform"
            }
          },
          "not_registered_platforms": {
            "type": "array",
            "description": "Plateformes vérifiées avec un résultat négatif.",
            "items": {
              "$ref": "#/components/schemas/SocialFootprintPlatform"
            }
          },
          "categories": {
            "type": "object",
            "description": "Nombre d'inscrits et ratio par catégorie de plateforme.",
            "additionalProperties": {
              "$ref": "#/components/schemas/SocialFootprintCategorySummary"
            }
          },
          "profiles": {
            "type": "object",
            "description": "Détails du profil par plateforme, indexés par plateforme, lorsque celle-ci les expose.",
            "additionalProperties": {
              "$ref": "#/components/schemas/SocialFootprintProfile"
            }
          }
        }
      },
      "EmailSocialFootprint": {
        "type": "object",
        "nullable": true,
        "description": "Empreinte sociale de l'adresse e-mail : les plateformes en ligne sur lesquelles elle est enregistrée. Présent uniquement lorsque `enable_social` a été défini et que la vérification s'est terminée. Chaque décompte peut être nul lorsqu'aucune donnée n'a été renvoyée pour celui-ci. `profiles_registered: 0` signifie que les plateformes ont été vérifiées et que l'adresse e-mail n'a été trouvée sur aucune d'entre elles - une réponse valide et facturable, ainsi qu'un signal fréquent d'identité synthétique.",
        "properties": {
          "profiles_registered": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes pour lesquelles l'inscription de l'adresse e-mail est confirmée.",
            "example": 5
          },
          "profiles_checked": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes évaluées pour l'inscription.",
            "example": 14
          },
          "names_found": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes ayant renvoyé un nom associé.",
            "example": 0
          },
          "photos_found": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes ayant renvoyé une photo de profil.",
            "example": 0
          },
          "communication_breadth": {
            "type": "integer",
            "nullable": true,
            "description": "Plateformes de communication sur lesquelles une présence a été détectée.",
            "example": 2
          },
          "digital_footprint_diversity": {
            "type": "integer",
            "nullable": true,
            "description": "Catégories de plateformes distinctes avec une présence détectée.",
            "example": 5
          },
          "digital_sophistication_index": {
            "type": "integer",
            "nullable": true,
            "description": "Indicateur composite de maturité numérique, de 0 à 10.",
            "example": 5
          },
          "engagement_depth_index": {
            "type": "integer",
            "nullable": true,
            "description": "Indicateur de richesse du profil, de 0 à 10.",
            "example": 3
          },
          "subscription_affordability_index": {
            "type": "integer",
            "nullable": true,
            "description": "Mix de plateformes gratuites vs payantes, 0-10.",
            "example": 2
          },
          "free_platforms": {
            "type": "integer",
            "nullable": true,
            "description": "Inscriptions sur des plateformes gratuites.",
            "example": 4
          },
          "full_paid_platforms": {
            "type": "integer",
            "nullable": true,
            "description": "Inscriptions sur des plateformes payantes.",
            "example": 0
          },
          "partial_paid_platforms": {
            "type": "integer",
            "nullable": true,
            "description": "Inscriptions sur des plateformes freemium.",
            "example": 1
          },
          "whatsapp_profile_completeness": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Basic",
              "Partial",
              "Complete",
              "Not Present",
              null
            ],
            "description": "Niveau de complétion du profil WhatsApp. Téléphone uniquement ; null pour l'e-mail.",
            "example": "Partial"
          },
          "registered_platforms": {
            "type": "array",
            "description": "Plateformes pour lesquelles l'inscription est confirmée.",
            "items": {
              "$ref": "#/components/schemas/SocialFootprintPlatform"
            }
          },
          "not_registered_platforms": {
            "type": "array",
            "description": "Plateformes vérifiées avec un résultat négatif.",
            "items": {
              "$ref": "#/components/schemas/SocialFootprintPlatform"
            }
          },
          "categories": {
            "type": "object",
            "description": "Nombre d'inscrits et ratio par catégorie de plateforme.",
            "additionalProperties": {
              "$ref": "#/components/schemas/SocialFootprintCategorySummary"
            }
          },
          "profiles": {
            "type": "object",
            "description": "Détails du profil par plateforme, indexés par plateforme, lorsque celle-ci les expose.",
            "additionalProperties": {
              "$ref": "#/components/schemas/SocialFootprintProfile"
            }
          }
        }
      },
      "KYBRegistryAddress": {
        "type": "object",
        "description": "Une adresse indiquée par le registre, sous le même format pour chaque pays et source de registre. Chaque clé est toujours présente ; une partie que le registre ne publie pas est null.",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true,
            "description": "Type d'adresse en minuscules : `registered` pour le siège social ; les autres types selon la désignation du registre (par exemple `postal`, `office`). `null` lorsque le registre ne précise pas la nature de l'adresse."
          },
          "address": {
            "type": "string",
            "description": "L'adresse complète sur une seule ligne. Toujours présente sur chaque adresse."
          },
          "street": {
            "type": "string",
            "nullable": true,
            "description": "Rue et numéro."
          },
          "city": {
            "type": "string",
            "nullable": true,
            "description": "Ville ou localité."
          },
          "postal_code": {
            "type": "string",
            "nullable": true,
            "description": "Code postal."
          },
          "region": {
            "type": "string",
            "nullable": true,
            "description": "Région, État ou province."
          },
          "country_code": {
            "type": "string",
            "nullable": true,
            "description": "Code pays ISO 3166-1 alpha-2."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Le libellé propre au registre pour l'adresse, lorsqu'il en fournit un."
          }
        },
        "required": [
          "type",
          "address",
          "street",
          "city",
          "postal_code",
          "region",
          "country_code",
          "description"
        ]
      },
      "KYBRegistryIndustry": {
        "type": "object",
        "description": "Une activité sous laquelle le registre classe l'entreprise, sous le même format pour chaque pays et source de registre.",
        "properties": {
          "code": {
            "type": "string",
            "nullable": true,
            "description": "Code d'activité tel qu'il figure sur le registre (par exemple `73110`)."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Libellé de l'activité, lorsque le registre en publie un."
          },
          "scheme": {
            "type": "string",
            "nullable": true,
            "description": "Système de classification, un nom par système quelle que soit la source l'ayant signalé : `UK SIC 2007`, `US SIC`, `NACE Rev. 2`, `NACE Rev. 2.1`, `NAF Rev. 2`, `CNAE`, `SBI`, `NOGA 2008`, `CAE Rev. 4`, `Canada SIC 1977` ; les autres systèmes nationaux conservent le nom propre du registre. Null lorsque le registre ne nomme pas le système."
          },
          "is_primary": {
            "type": "boolean",
            "description": "Vrai pour l'activité principale de l'entreprise. Exactement une entrée est principale lorsque la liste n'est pas vide."
          }
        },
        "required": [
          "code",
          "description",
          "scheme",
          "is_primary"
        ]
      },
      "KYBRegistryShareholding": {
        "type": "object",
        "nullable": true,
        "description": "Ce qu'un propriétaire détient, sous le même format pour chaque pays et chaque source de registre. Null lorsque le registre ne mentionne aucune détention. Une fourchette (par exemple les 25-50% d'un PSC britannique) n'est pas une participation : `percentage` est null et la fourchette reste dans `ownership_min_shares` / `ownership_max_shares`.",
        "properties": {
          "share_class": {
            "type": "string",
            "nullable": true,
            "description": "Catégorie ou type d'actions selon la dénomination du registre."
          },
          "number_of_shares": {
            "type": "number",
            "nullable": true,
            "description": "Nombre d'actions détenues."
          },
          "currency": {
            "type": "string",
            "nullable": true,
            "description": "Devise ISO 4217 des valeurs ci-dessous."
          },
          "nominal_value": {
            "type": "number",
            "nullable": true,
            "description": "Valeur nominale par action."
          },
          "total_value": {
            "type": "number",
            "nullable": true,
            "description": "Valeur totale de la participation."
          },
          "percentage": {
            "type": "number",
            "nullable": true,
            "description": "Participation exacte en pourcentage, à quatre décimales."
          }
        },
        "required": [
          "share_class",
          "number_of_shares",
          "currency",
          "nominal_value",
          "total_value",
          "percentage"
        ]
      },
      "KYBRegistryOwnership": {
        "type": "object",
        "description": "Le résultat du niveau de l'actionnariat (Actionnaires / UBO), sous le même format pour chaque pays et source de registre.",
        "properties": {
          "status": {
            "type": "string",
            "nullable": true,
            "enum": [
              "not_requested",
              "pending",
              "delivered",
              "not_held",
              "unavailable",
              null
            ],
            "description": "`delivered` lorsque le registre a publié l'actionnariat ; `not_held` lorsque le registre d'actionnariat a répondu et ne répertorie pas du tout l'entreprise (voir `unavailable_reason`) ; `unavailable` lorsqu'il n'a pas fourni les données d'actionnariat pour toute autre raison (voir `unavailable_reason`) ; `pending` pendant que le registre les récupère encore ; `not_requested` pour le niveau Basic."
          },
          "tier_requested": {
            "type": "string",
            "nullable": true,
            "enum": [
              "basic",
              "shareholders",
              "ubo",
              null
            ],
            "description": "Le niveau commandé par le workflow."
          },
          "tier_delivered": {
            "type": "string",
            "nullable": true,
            "enum": [
              "basic",
              "shareholders",
              "ubo",
              null
            ],
            "description": "Le niveau fourni par le registre (et qui est facturé). Une requête UBO dont la réponse ne contient que des actionnaires directs est `shareholders`."
          },
          "unavailable_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "no_owners_on_record",
              "no_natural_person_owner",
              "ownership_section_unavailable",
              "company_not_found",
              "ambiguous_company_match",
              "missing_registration_number",
              "entity_type_not_covered",
              "provider_unavailable",
              "other",
              null
            ],
            "description": "Raison pour laquelle un niveau d'actionnariat demandé n'a pas été fourni. Nul sauf si `status` est `unavailable` ou `pending`."
          },
          "direct_ownership_complete": {
            "type": "boolean",
            "nullable": true,
            "description": "Vrai lorsque la somme des participations déclarées des actionnaires directs atteint 100 % (à un point de pourcentage près pour l'arrondi) ; faux dans le cas contraire ; null lorsque l'actionnariat n'a pas été fourni ou qu'une participation n'est pas déclarée."
          },
          "unresolved": {
            "type": "array",
            "description": "Parties de la chaîne d'actionnariat que le registre n'a pas pu résoudre, par exemple aucune structure de groupe enregistrée au-dessus des propriétaires directs.",
            "items": {
              "type": "object",
              "properties": {
                "reason": {
                  "type": "string"
                },
                "section": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          }
        },
        "required": [
          "status",
          "tier_requested",
          "tier_delivered",
          "unavailable_reason",
          "direct_ownership_complete",
          "unresolved"
        ]
      },
      "KYBRegistryData": {
        "type": "object",
        "nullable": true,
        "description": "Détails normalisés du registre Didit pour l'entreprise : le résultat sur l'actionnariat (`ownership_error`, `section_errors`, `ubo_resolution`, `lite_enrichment`), les corrections apportées avec update-data et les faits du registre qui n'ont pas de champ propre. Ils ne comportent jamais l'enregistrement propre de la source du registre. Chaque clé est facultative et présente uniquement lorsque l'entreprise a une valeur pour celle-ci ; de nouvelles clés peuvent être ajoutées. Consultez les champs canoniques (`addresses`, `industries`, `ownership`, `beneficial_owners[].shareholding`) pour tout ce qu'ils couvrent.",
        "properties": {
          "company_name": {
            "type": "string",
            "description": "Nom de l'entreprise tel que corrigé dans la console."
          },
          "registration_number": {
            "type": "string",
            "description": "Numéro d'immatriculation tel qu'indiqué par le registre ou par une correction dans la console."
          },
          "country_code": {
            "type": "string",
            "description": "Pays de l'immatriculation tel qu'indiqué par le registre ou par une correction dans la console."
          },
          "region": {
            "type": "string",
            "description": "Région ou État de l'immatriculation."
          },
          "incorporation_date": {
            "type": "string",
            "description": "Date de constitution (ISO 8601)."
          },
          "registration_date": {
            "type": "string",
            "description": "Date d'immatriculation (ISO 8601) lorsque le registre en indique une distincte de la date de constitution."
          },
          "dissolution_date": {
            "type": "string",
            "description": "Date de dissolution (ISO 8601) lorsque le registre en indique une."
          },
          "tax_number": {
            "type": "string",
            "description": "Identifiant fiscal."
          },
          "vat_number": {
            "type": "string",
            "description": "Numéro de TVA."
          },
          "legal_address": {
            "type": "string",
            "description": "Adresse légale telle que corrigée dans la console."
          },
          "registered_address": {
            "type": "string",
            "description": "Adresse enregistrée telle qu'indiquée par le registre."
          },
          "company_type": {
            "type": "string",
            "description": "Forme juridique."
          },
          "registry_status": {
            "type": "string",
            "description": "Statut de l'entreprise auprès du registre."
          },
          "verification_status": {
            "type": "string",
            "description": "Statut de vérification."
          },
          "alternative_names": {
            "type": "string",
            "description": "Autres noms sous lesquels l'entreprise exerce ou a exercé ses activités commerciales."
          },
          "nature_of_business": {
            "type": "string",
            "description": "Description de l'activité."
          },
          "registered_capital": {
            "type": "string",
            "description": "Capital social tel qu'indiqué."
          },
          "registered_capital_amount": {
            "type": "string",
            "description": "Montant du capital social, sous forme de chaîne décimale."
          },
          "registered_capital_currency": {
            "type": "string",
            "description": "Devise du capital social (ISO 4217)."
          },
          "website": {
            "type": "string",
            "description": "Site web."
          },
          "email": {
            "type": "string",
            "description": "E-mail de contact."
          },
          "phone": {
            "type": "string",
            "description": "Téléphone de contact."
          },
          "legal_entity_identifier": {
            "type": "string",
            "description": "Identifiant d'entité juridique (LEI)."
          },
          "location_of_registration": {
            "type": "string",
            "description": "Lieu d'enregistrement."
          },
          "control_scheme": {
            "type": "string",
            "description": "Régime de gouvernance lorsque le registre l'indique."
          },
          "ownership_error": {
            "type": "string",
            "enum": [
              "no_owners_on_record",
              "no_natural_person_owner",
              "ownership_section_unavailable",
              "company_not_found",
              "ambiguous_company_match",
              "missing_registration_number",
              "entity_type_not_covered",
              "provider_unavailable",
              "other"
            ],
            "description": "Raison pour laquelle un niveau d'actionnariat demandé n'a pas été fourni, selon les mêmes codes que `ownership.unavailable_reason`. `no_owners_on_record` (le registre a répondu et ne mentionne aucun propriétaire) et `ownership_section_unavailable` (le registre n'a pas renvoyé la section relative à l'actionnariat) constituent des constats différents."
          },
          "section_errors": {
            "type": "object",
            "description": "Sections non renvoyées par le registre, indexées par section (`officers`, `shareholders`, `group_structure`). Une section répertoriée ici n'a jamais été transmise : une liste vide à côté de celle-ci n'indique rien sur l'entreprise.",
            "additionalProperties": {
              "$ref": "#/components/schemas/KYBRegistrySectionError"
            }
          },
          "ubo_resolution": {
            "$ref": "#/components/schemas/KYBRegistryUboResolution"
          },
          "lite_enrichment": {
            "$ref": "#/components/schemas/KYBRegistryLiteEnrichment"
          },
          "registry_metadata": {
            "type": "object",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ]
            },
            "description": "Les champs propres au registre pour l'entreprise, indexés comme le registre les nomme, sous forme de valeurs brutes (enregistrements hérités). Seuls les champs examinés en tant que faits du registre sont inclus."
          },
          "registry_sources": {
            "type": "array",
            "description": "Les registres officiels depuis lesquels l'enregistrement a été lu (anciens enregistrements). Les autres sources ne sont pas nommées.",
            "items": {
              "$ref": "#/components/schemas/KYBRegistrySource"
            }
          },
          "previous_names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Noms sous lesquels l'entreprise était précédemment immatriculée (enregistrements historiques)."
          },
          "parent_companies": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Sociétés mères mentionnées par le registre (enregistrements historiques)."
          },
          "documents_available": {
            "type": "integer",
            "description": "Nombre de dépôts proposés par le registre pour l'entreprise (anciens enregistrements)."
          }
        }
      },
      "KYBRegistryGroupCompany": {
        "type": "object",
        "description": "Une société du groupe d'entreprises, selon son identité au registre.",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de l'entreprise."
          },
          "country_code": {
            "type": "string",
            "nullable": true,
            "description": "Pays d'immatriculation."
          },
          "registration_number": {
            "type": "string",
            "nullable": true,
            "description": "Numéro d'immatriculation."
          }
        },
        "required": [
          "name",
          "country_code",
          "registration_number"
        ]
      },
      "KYBRegistryUboResolution": {
        "type": "object",
        "description": "Manière dont le niveau UBO a parcouru la chaîne de détention au-dessus de l'entreprise.",
        "properties": {
          "parent_chain": {
            "type": "array",
            "description": "Sociétés mères, de la société mère ultime jusqu'à l'entreprise.",
            "items": {
              "$ref": "#/components/schemas/KYBRegistryGroupCompany"
            }
          },
          "subsidiaries": {
            "type": "array",
            "description": "Filiales directes de l'entreprise au sein de son groupe.",
            "items": {
              "$ref": "#/components/schemas/KYBRegistryGroupCompany"
            }
          },
          "unresolved": {
            "type": "array",
            "description": "Parties de la chaîne que le registre n'a pas pu résoudre (les mêmes entrées que `ownership.unresolved`).",
            "items": {
              "type": "object",
              "properties": {
                "reason": {
                  "type": "string",
                  "description": "Raison, par exemple `no_group_structure_on_record`, `selected_company_not_in_group_structure` ou `section_error`."
                },
                "section": {
                  "type": "string",
                  "nullable": true,
                  "description": "La section concernée, par exemple `group_structure`."
                }
              },
              "required": [
                "reason",
                "section"
              ]
            }
          }
        },
        "required": [
          "parent_chain",
          "subsidiaries",
          "unresolved"
        ]
      },
      "KYBRegistrySectionError": {
        "type": "object",
        "description": "Une section que le registre n'a pas renvoyée.",
        "properties": {
          "status_code": {
            "type": "integer",
            "nullable": true,
            "description": "Le statut renvoyé par le registre pour la section."
          }
        },
        "required": [
          "status_code"
        ]
      },
      "KYBRegistryLiteEnrichment": {
        "type": "object",
        "description": "Champs de profil Lite vides qu'une autre source du registre du pays a complétés. La source n'est pas nommée.",
        "properties": {
          "fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Les champs de l'entreprise qui ont été renseignés."
          },
          "people_added": {
            "type": "integer",
            "description": "Nombre de dirigeants ou de propriétaires ajoutés."
          }
        },
        "required": [
          "fields",
          "people_added"
        ]
      },
      "KYBRegistrySource": {
        "type": "object",
        "description": "Un registre officiel à partir duquel l'enregistrement a été lu. Seuls les registres officiels d'État, les régulateurs et le système officiel d'identifiants sont mentionnés ; toute autre source est exclue.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nom du registre, par exemple `UK Companies House`."
          },
          "source_type": {
            "type": "string",
            "enum": [
              "official"
            ],
            "description": "Toujours `official`."
          }
        },
        "required": [
          "name",
          "source_type"
        ]
      },
      "KYBOwnershipStructure": {
        "type": "object",
        "nullable": true,
        "description": "La table de capitalisation prouvée par le registre, telle qu'elle se présentait lors de la livraison du niveau d'actionnariat : `shareholders` et `beneficial_owners` directs. Null lorsque le registre n'a prouvé aucun actionnariat. Elle ne contient jamais les lignes propres à la source du registre ; lisez `company.beneficial_owners` et `company.ownership` pour l'enregistrement actuel.",
        "properties": {
          "shareholders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KYBOwnershipStructureOwner"
            }
          },
          "beneficial_owners": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KYBOwnershipStructureOwner"
            }
          }
        },
        "required": [
          "shareholders",
          "beneficial_owners"
        ]
      },
      "KYBOwnershipStructureOwner": {
        "type": "object",
        "description": "Un propriétaire dans l'instantané de l'actionnariat : la même identité de registre et la même part que dans `company.beneficial_owners[]`, ainsi que son `shareholding` canonique.",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nom du propriétaire tel qu'indiqué par le registre."
          },
          "first_name": {
            "type": "string",
            "nullable": true,
            "description": "Prénom, pour une personne physique, lorsque le registre le mentionne."
          },
          "last_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de famille, pour une personne physique, lorsque le registre le mentionne."
          },
          "date_of_birth": {
            "type": "string",
            "nullable": true,
            "description": "Date de naissance (ISO 8601) lorsque le registre la publie."
          },
          "country_of_birth": {
            "type": "string",
            "nullable": true,
            "description": "Pays de naissance lorsque le registre le publie."
          },
          "company_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de l'entreprise, pour un propriétaire personne morale."
          },
          "registration_number": {
            "type": "string",
            "nullable": true,
            "description": "Numéro d'immatriculation, pour une personne morale propriétaire."
          },
          "entity_type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "person",
              "company",
              null
            ],
            "description": "Indique si le propriétaire est une personne physique ou une entreprise."
          },
          "nationality": {
            "type": "string",
            "nullable": true,
            "description": "Nationalité lorsque le registre l'indique."
          },
          "designation": {
            "type": "string",
            "nullable": true,
            "description": "Le titre ou le rôle du propriétaire tel que le registre l'indique."
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "`shareholder` pour un détenteur direct, `ubo` pour un bénéficiaire effectif."
          },
          "ownership_min_shares": {
            "type": "string",
            "nullable": true,
            "description": "Limite inférieure de la participation, en pourcentage (égale à la limite supérieure pour une participation exacte)."
          },
          "ownership_max_shares": {
            "type": "string",
            "nullable": true,
            "description": "Limite supérieure de la participation, en pourcentage."
          },
          "voting_min_shares": {
            "type": "string",
            "nullable": true,
            "description": "Limite inférieure des droits de vote, en pourcentage."
          },
          "voting_max_shares": {
            "type": "string",
            "nullable": true,
            "description": "Limite supérieure des droits de vote, en pourcentage."
          },
          "appointment_date": {
            "type": "string",
            "nullable": true,
            "description": "Date de début de la fonction ou du mandat (ISO 8601)."
          },
          "is_active": {
            "type": "boolean",
            "nullable": true,
            "description": "False pour un ancien propriétaire."
          },
          "shareholding": {
            "$ref": "#/components/schemas/KYBRegistryShareholding"
          }
        },
        "required": [
          "name",
          "first_name",
          "last_name",
          "date_of_birth",
          "country_of_birth",
          "company_name",
          "registration_number",
          "entity_type",
          "nationality",
          "designation",
          "roles",
          "ownership_min_shares",
          "ownership_max_shares",
          "voting_min_shares",
          "voting_max_shares",
          "appointment_date",
          "is_active",
          "shareholding"
        ]
      },
      "DigitalIdWalletApiWalletVerificationError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Code stable lisible par machine, par exemple wallet_unavailable."
          },
          "detail": {
            "type": "string"
          }
        },
        "required": [
          "detail",
          "error"
        ]
      },
      "DigitalIdWalletApiWalletVerificationStartForbidden": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/DigitalIdWalletApiClientCredentialsForbiddenErrorMessage"
          },
          {
            "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
          }
        ]
      },
      "DigitalIdWalletApiClientCredentialsForbiddenErrorMessage": {
        "type": "object",
        "properties": {
          "detail": {
            "type": "string",
            "default": "Forbidden - User doesn't have permission"
          }
        }
      },
      "DigitalIdWalletApiWalletVerificationStartBadRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationError"
          },
          {
            "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationFieldErrors"
          }
        ]
      },
      "DigitalIdWalletApiWalletVerificationFieldErrors": {
        "type": "object",
        "description": "Erreurs de validation de la requête : chaque champ rejeté avec ses messages.",
        "additionalProperties": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "DigitalIdWalletApiWalletVerificationResponse": {
        "type": "object",
        "description": "Une vérification de portefeuille autonome, telle que renvoyée par chaque endpoint de portefeuille.",
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "wallet_verification": {
            "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResult"
          },
          "vendor_data": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "L'objet de métadonnées envoyé au démarrage, ou null."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "created_at",
          "metadata",
          "request_id",
          "vendor_data",
          "wallet_verification"
        ]
      },
      "DigitalIdWalletApiWalletVerificationResult": {
        "type": "object",
        "properties": {
          "wallet": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiWallet"
              }
            ],
            "readOnly": true
          },
          "country": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Non terminé tant qu'il est en attente, puis Approuvé (vérifié) ou Refusé."
          },
          "outcome": {
            "$ref": "#/components/schemas/DigitalIdWalletApiWalletVerificationResultOutcomeEnum"
          },
          "error": {
            "type": "string",
            "nullable": true,
            "readOnly": true
          },
          "interaction": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiInteractionEnum"
              }
            ],
            "readOnly": true
          },
          "simulated": {
            "type": "boolean",
            "readOnly": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "next_action": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiWalletNextAction"
              }
            ],
            "nullable": true,
            "readOnly": true
          },
          "identity": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiWalletIdentity"
              }
            ],
            "nullable": true,
            "readOnly": true
          },
          "attributes": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "readOnly": true
          },
          "level_of_assurance": {
            "type": "string",
            "nullable": true
          },
          "verified_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "signature_valid": {
            "type": "boolean",
            "nullable": true,
            "description": "Vrai dès que la signature de l'attestation a été vérifiée ; null pour une attestation simulée."
          },
          "credential_type": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "attributes",
          "country",
          "credential_type",
          "error",
          "expires_at",
          "identity",
          "interaction",
          "level_of_assurance",
          "next_action",
          "outcome",
          "signature_valid",
          "simulated",
          "status",
          "verified_at",
          "wallet"
        ]
      },
      "DigitalIdWalletApiWalletIdentity": {
        "type": "object",
        "properties": {
          "full_name": {
            "type": "string",
            "nullable": true
          },
          "first_name": {
            "type": "string",
            "nullable": true
          },
          "last_name": {
            "type": "string",
            "nullable": true
          },
          "date_of_birth": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "nationality": {
            "type": "string",
            "nullable": true,
            "description": "Nationalité ISO3, uniquement lorsque le portefeuille en atteste une (jamais déduite)."
          },
          "issuing_state": {
            "type": "string",
            "description": "Pays ISO3 dont le système a délivré l'identité."
          }
        },
        "required": [
          "date_of_birth",
          "first_name",
          "full_name",
          "issuing_state",
          "last_name",
          "nationality"
        ]
      },
      "DigitalIdWalletApiWalletNextAction": {
        "type": "object",
        "properties": {
          "type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiWalletNextActionTypeEnum"
              }
            ],
            "description": "redirect : redirigez le navigateur de l'utilisateur vers url. confirm_in_app : affichez verification_code à l'utilisateur, qui vérifie qu'il correspond au code dans son application de portefeuille et confirme là-bas ; puis interrogez. request_digital_credential : lors d'un geste utilisateur sur l'origine initiale, interrogez le portefeuille avec digital_credentials.request, puis envoyez ce qu'il renvoie à POST .../verifications/{request_id}/response/.\n\n* `redirect` - redirect\n* `confirm_in_app` - confirm_in_app\n* `request_digital_credential` - request_digital_credential"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "redirect uniquement : là où l'utilisateur se connecte avec le portefeuille."
          },
          "digital_credentials": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiWalletDigitalCredentialsRequest"
              }
            ],
            "description": "request_digital_credential uniquement : la requête à transmettre au portefeuille."
          },
          "verification_code": {
            "type": "string",
            "description": "confirm_in_app uniquement : le code de comparaison à 4 chiffres que l'application de portefeuille affiche également."
          },
          "poll_interval_seconds": {
            "type": "integer",
            "description": "confirm_in_app uniquement : fréquence d'appel de POST .../verifications/{request_id}/poll/ pour un retour rapide. Didit interroge également les connexions en attente en arrière-plan, de sorte que le webhook signale le résultat même si vous n'effectuez pas de scrutation."
          }
        },
        "required": [
          "type"
        ]
      },
      "DigitalIdWalletApiWalletNextActionTypeEnum": {
        "enum": [
          "redirect",
          "confirm_in_app",
          "request_digital_credential"
        ],
        "type": "string",
        "description": "* `redirect` - redirect\n* `confirm_in_app` - confirm_in_app\n* `request_digital_credential` - request_digital_credential"
      },
      "DigitalIdWalletApiInteractionEnum": {
        "enum": [
          "redirect",
          "in_app",
          "digital_credentials"
        ],
        "type": "string",
        "description": "* `redirect` - redirect\n* `in_app` - in_app\n* `digital_credentials` - digital_credentials"
      },
      "DigitalIdWalletApiWalletVerificationResultOutcomeEnum": {
        "enum": [
          "pending",
          "verified",
          "cancelled",
          "timeout",
          "failed"
        ],
        "type": "string",
        "description": "* `pending` - En attente\n* `verified` - Vérifié\n* `cancelled` - Annulé par l'utilisateur\n* `timeout` - Délai d'attente dépassé\n* `failed` - Échoué"
      },
      "DigitalIdWalletApiWallet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identifiant de catalogue du portefeuille, par exemple bankid_se."
          },
          "name": {
            "type": "string"
          },
          "issuing_authority": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "issuing_authority",
          "name"
        ]
      },
      "DigitalIdWalletApiEudiWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification d'identité EUDI Wallet (AUT, BEL, BGR, HRV, CYP, CZE, DNK, EST, FIN, FRA, DEU, GRC, HUN, IRL, ITA, LVA, LTU, LUX, MLT, NLD, POL, PRT, ROU, SVK, SVN, ESP, SWE, ISL, LIE, NOR).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiEudiWalletVerificationStartCountryEnum"
              }
            ],
            "description": "Pays ISO 3166-1 alpha-3 de l'identité EUDI Wallet.\n\n* `AUT` - AUT\n* `BEL` - BEL\n* `BGR` - BGR\n* `HRV` - HRV\n* `CYP` - CYP\n* `CZE` - CZE\n* `DNK` - DNK\n* `EST` - EST\n* `FIN` - FIN\n* `FRA` - FRA\n* `DEU` - DEU\n* `GRC` - GRC\n* `HUN` - HUN\n* `IRL` - IRL\n* `ITA` - ITA\n* `LVA` - LVA\n* `LTU` - LTU\n* `LUX` - LUX\n* `MLT` - MLT\n* `NLD` - NLD\n* `POL` - POL\n* `PRT` - PRT\n* `ROU` - ROU\n* `SVK` - SVK\n* `SVN` - SVN\n* `ESP` - ESP\n* `SWE` - SWE\n* `ISL` - ISL\n* `LIE` - LIE\n* `NOR` - NOR"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "country",
          "return_url"
        ]
      },
      "DigitalIdWalletApiDeviceEnum": {
        "enum": [
          "same_device",
          "cross_device"
        ],
        "type": "string",
        "description": "* `same_device` - same_device\n* `cross_device` - cross_device"
      },
      "DigitalIdWalletApiEudiWalletVerificationStartCountryEnum": {
        "enum": [
          "AUT",
          "BEL",
          "BGR",
          "HRV",
          "CYP",
          "CZE",
          "DNK",
          "EST",
          "FIN",
          "FRA",
          "DEU",
          "GRC",
          "HUN",
          "IRL",
          "ITA",
          "LVA",
          "LTU",
          "LUX",
          "MLT",
          "NLD",
          "POL",
          "PRT",
          "ROU",
          "SVK",
          "SVN",
          "ESP",
          "SWE",
          "ISL",
          "LIE",
          "NOR"
        ],
        "type": "string",
        "description": "* `AUT` - AUT\n* `BEL` - BEL\n* `BGR` - BGR\n* `HRV` - HRV\n* `CYP` - CYP\n* `CZE` - CZE\n* `DNK` - DNK\n* `EST` - EST\n* `FIN` - FIN\n* `FRA` - FRA\n* `DEU` - DEU\n* `GRC` - GRC\n* `HUN` - HUN\n* `IRL` - IRL\n* `ITA` - ITA\n* `LVA` - LVA\n* `LTU` - LTU\n* `LUX` - LUX\n* `MLT` - MLT\n* `NLD` - NLD\n* `POL` - POL\n* `PRT` - PRT\n* `ROU` - ROU\n* `SVK` - SVK\n* `SVN` - SVN\n* `ESP` - ESP\n* `SWE` - SWE\n* `ISL` - ISL\n* `LIE` - LIE\n* `NOR` - NOR"
      },
      "DigitalIdWalletApiConnectidWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification d'identité ConnectID (AUS).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiConnectidWalletVerificationStartCountryEnum"
              }
            ],
            "default": "AUS",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité ConnectID. La valeur par défaut est AUS, le seul pays desservi.\n\n* `AUS` - AUS"
          },
          "authorisation_server_id": {
            "type": "string",
            "minLength": 1,
            "description": "Identifiant du serveur d'autorisation sélectionné avec le sélecteur de banque de ConnectID. Dans la sandbox, la valeur par défaut est Mock Bank A.",
            "maxLength": 36
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiConnectidWalletVerificationStartCountryEnum": {
        "enum": [
          "AUS"
        ],
        "type": "string",
        "description": "* `AUS` - AUS"
      },
      "DigitalIdWalletApiAudkenniWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification Auðkenni (ISL).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiAudkenniWalletVerificationStartCountryEnum"
              }
            ],
            "default": "ISL",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Auðkenni. La valeur par défaut est ISL, le seul pays desservi.\n\n* `ISL` - ISL"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiAudkenniWalletVerificationStartCountryEnum": {
        "enum": [
          "ISL"
        ],
        "type": "string",
        "description": "* `ISL` - ISL"
      },
      "DigitalIdWalletApiFranceconnectWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification FranceConnect (FRA).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiFranceconnectWalletVerificationStartCountryEnum"
              }
            ],
            "default": "FRA",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité FranceConnect. La valeur par défaut est FRA, le seul pays desservi.\n\n* `FRA` - FRA"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiFranceconnectWalletVerificationStartCountryEnum": {
        "enum": [
          "FRA"
        ],
        "type": "string",
        "description": "* `FRA` - FRA"
      },
      "DigitalIdWalletApiDiiaWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification d'identité Diia (UKR).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDiiaWalletVerificationStartCountryEnum"
              }
            ],
            "default": "UKR",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Diia. La valeur par défaut est UKR, le seul pays desservi.\n\n* `UKR` - UKR"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiDiiaWalletVerificationStartCountryEnum": {
        "enum": [
          "UKR"
        ],
        "type": "string",
        "description": "* `UKR` - UKR"
      },
      "DigitalIdWalletApiMojeidWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification MojeID (CZE).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountryE2dEnum"
              }
            ],
            "default": "CZE",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité MojeID. La valeur par défaut est CZE, le seul pays pris en charge.\n\n* `CZE` - CZE"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiCountryE2dEnum": {
        "enum": [
          "CZE"
        ],
        "type": "string",
        "description": "* `CZE` - CZE"
      },
      "DigitalIdWalletApiBankidCzWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification d'identité Bank iD (CZE).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountryE2dEnum"
              }
            ],
            "default": "CZE",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Bank iD. La valeur par défaut est CZE, le seul pays desservi.\n\n* `CZE` - CZE"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiEparakstsMobileWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification eParaksts mobile (LVA).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiEparakstsMobileWalletVerificationStartCountryEnum"
              }
            ],
            "default": "LVA",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité mobile eParaksts. La valeur par défaut est LVA, le seul pays pris en charge.\n\n* `LVA` - LVA"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiEparakstsMobileWalletVerificationStartCountryEnum": {
        "enum": [
          "LVA"
        ],
        "type": "string",
        "description": "* `LVA` - LVA"
      },
      "DigitalIdWalletApiIdcardEeWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification par carte d'identité estonienne (EST).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiIdcardEeWalletVerificationStartCountryEnum"
              }
            ],
            "default": "EST",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Estonian ID-card. La valeur par défaut est EST, le seul pays desservi.\n\n* `EST` - EST"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiIdcardEeWalletVerificationStartCountryEnum": {
        "enum": [
          "EST"
        ],
        "type": "string",
        "description": "* `EST` - EST"
      },
      "DigitalIdWalletApiMobileIdWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification Mobile-ID (EST, LTU).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiMobileIdWalletVerificationStartCountryEnum"
              }
            ],
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Mobile-ID.\n\n* `EST` - EST\n* `LTU` - LTU"
          },
          "personal_code": {
            "type": "string",
            "minLength": 1,
            "description": "Le code national d'identification personnelle de l'utilisateur. Il s'adresse à l'application Mobile-ID de l'utilisateur ; l'utilisateur confirme le code de comparaison et saisit son PIN dans l'application. Ne collectez jamais le PIN.",
            "pattern": "^[0-9-]{6,20}$"
          },
          "phone_number": {
            "type": "string",
            "minLength": 1,
            "description": "Le numéro de téléphone Mobile-ID au format E.164 (+372... ou +370...).",
            "maxLength": 16
          }
        },
        "required": [
          "country",
          "personal_code",
          "phone_number"
        ]
      },
      "DigitalIdWalletApiMobileIdWalletVerificationStartCountryEnum": {
        "enum": [
          "EST",
          "LTU"
        ],
        "type": "string",
        "description": "* `EST` - EST\n* `LTU` - LTU"
      },
      "DigitalIdWalletApiSmartIdWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification Smart-ID (EST, LVA, LTU, BEL).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiSmartIdWalletVerificationStartCountryEnum"
              }
            ],
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Smart-ID.\n\n* `EST` - EST\n* `LVA` - LVA\n* `LTU` - LTU\n* `BEL` - BEL"
          },
          "personal_code": {
            "type": "string",
            "minLength": 1,
            "description": "Le code national d'identification personnelle de l'utilisateur. Il s'adresse à l'application Smart-ID de l'utilisateur ; l'utilisateur confirme le code de comparaison et saisit son PIN dans l'application. Ne collectez jamais le PIN.",
            "pattern": "^[0-9-]{6,20}$"
          }
        },
        "required": [
          "country",
          "personal_code"
        ]
      },
      "DigitalIdWalletApiSmartIdWalletVerificationStartCountryEnum": {
        "enum": [
          "EST",
          "LVA",
          "LTU",
          "BEL"
        ],
        "type": "string",
        "description": "* `EST` - EST\n* `LVA` - LVA\n* `LTU` - LTU\n* `BEL` - BEL"
      },
      "DigitalIdWalletApiGovukWalletWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification GOV.UK Wallet (GBR).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountry520Enum"
              }
            ],
            "default": "GBR",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité GOV.UK Wallet. La valeur par défaut est GBR, le seul pays pris en charge.\n\n* `GBR` - GBR"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiCountry520Enum": {
        "enum": [
          "GBR"
        ],
        "type": "string",
        "description": "* `GBR` - GBR"
      },
      "DigitalIdWalletApiOneidWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification OneID (GBR).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountry520Enum"
              }
            ],
            "default": "GBR",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité OneID. La valeur par défaut est GBR, le seul pays pris en charge.\n\n* `GBR` - GBR"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiGovbrWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification gov.br (BRA).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiGovbrWalletVerificationStartCountryEnum"
              }
            ],
            "default": "BRA",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité gov.br. La valeur par défaut est BRA, le seul pays pris en charge.\n\n* `BRA` - BRA"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiGovbrWalletVerificationStartCountryEnum": {
        "enum": [
          "BRA"
        ],
        "type": "string",
        "description": "* `BRA` - BRA"
      },
      "DigitalIdWalletApiUaePassWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification UAE PASS (ARE).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiUaePassWalletVerificationStartCountryEnum"
              }
            ],
            "default": "ARE",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité UAE PASS. La valeur par défaut est ARE, le seul pays pris en charge.\n\n* `ARE` - ARE"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiUaePassWalletVerificationStartCountryEnum": {
        "enum": [
          "ARE"
        ],
        "type": "string",
        "description": "* `ARE` - ARE"
      },
      "DigitalIdWalletApiFrejaidWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification Freja eID (SWE).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountryEe9Enum"
              }
            ],
            "default": "SWE",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Freja eID. La valeur par défaut est SWE, le seul pays pris en charge.\n\n* `SWE` - SWE"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiCountryEe9Enum": {
        "enum": [
          "SWE"
        ],
        "type": "string",
        "description": "* `SWE` - SWE"
      },
      "DigitalIdWalletApiPersonalausweisWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification Personalausweis (DEU).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiPersonalausweisWalletVerificationStartCountryEnum"
              }
            ],
            "default": "DEU",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Personalausweis. La valeur par défaut est DEU, le seul pays pris en charge.\n\n* `DEU` - DEU"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiPersonalausweisWalletVerificationStartCountryEnum": {
        "enum": [
          "DEU"
        ],
        "type": "string",
        "description": "* `DEU` - DEU"
      },
      "DigitalIdWalletApiFtnWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification Finnish Trust Network (FIN).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiFtnWalletVerificationStartCountryEnum"
              }
            ],
            "default": "FIN",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Finnish Trust Network. La valeur par défaut est FIN, le seul pays desservi.\n\n* `FIN` - FIN"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiFtnWalletVerificationStartCountryEnum": {
        "enum": [
          "FIN"
        ],
        "type": "string",
        "description": "* `FIN` - FIN"
      },
      "DigitalIdWalletApiIdinWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification iDIN (NLD).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiIdinWalletVerificationStartCountryEnum"
              }
            ],
            "default": "NLD",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité iDIN. La valeur par défaut est NLD, le seul pays pris en charge.\n\n* `NLD` - NLD"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiIdinWalletVerificationStartCountryEnum": {
        "enum": [
          "NLD"
        ],
        "type": "string",
        "description": "* `NLD` - NLD"
      },
      "DigitalIdWalletApiItsmeWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification itsme (BEL, LUX, NLD).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiItsmeWalletVerificationStartCountryEnum"
              }
            ],
            "description": "Pays ISO 3166-1 alpha-3 de l'identité itsme.\n\n* `BEL` - BEL\n* `LUX` - LUX\n* `NLD` - NLD"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "country",
          "return_url"
        ]
      },
      "DigitalIdWalletApiItsmeWalletVerificationStartCountryEnum": {
        "enum": [
          "BEL",
          "LUX",
          "NLD"
        ],
        "type": "string",
        "description": "* `BEL` - BEL\n* `LUX` - LUX\n* `NLD` - NLD"
      },
      "DigitalIdWalletApiBuypassWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification d'identité Buypass ID (NOR).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountryAfcEnum"
              }
            ],
            "default": "NOR",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Buypass ID. La valeur par défaut est NOR, le seul pays desservi.\n\n* `NOR` - NOR"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiCountryAfcEnum": {
        "enum": [
          "NOR"
        ],
        "type": "string",
        "description": "* `NOR` - NOR"
      },
      "DigitalIdWalletApiVippsWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification Vipps (NOR).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountryAfcEnum"
              }
            ],
            "default": "NOR",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Vipps. La valeur par défaut est NOR, le seul pays pris en charge.\n\n* `NOR` - NOR"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiBankidNoWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification d'identité BankID (NOR).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountryAfcEnum"
              }
            ],
            "default": "NOR",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité BankID. La valeur par défaut est NOR, le seul pays desservi.\n\n* `NOR` - NOR"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiBankidSeWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification d'identité BankID (SWE).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiCountryEe9Enum"
              }
            ],
            "default": "SWE",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité BankID. La valeur par défaut est SWE, le seul pays desservi.\n\n* `SWE` - SWE"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiMitidWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification MitID (DNK).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiMitidWalletVerificationStartCountryEnum"
              }
            ],
            "default": "DNK",
            "description": "Pays ISO 3166-1 alpha-3 de l'identité MitID. La valeur par défaut est DNK, le seul pays pris en charge.\n\n* `DNK` - DNK"
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "minLength": 1,
            "description": "URL HTTPS vers laquelle le navigateur de l'utilisateur est redirigé après l'utilisation du portefeuille, avec request_id et result ajoutés. Son hôte doit être enregistré dans les allowed_return_hosts de l'application (ou être son domaine en marque blanche). Ne vous fiez jamais à result à lui seul : lisez le résultat avec GET .../verifications/{request_id}/ ou le webhook.",
            "maxLength": 2048
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiDeviceEnum"
              }
            ],
            "default": "same_device",
            "description": "same_device lorsque l'utilisateur se connecte sur l'appareil affichant votre page, cross_device lorsqu'il en utilise un autre (par exemple le code QR de BankID).\n\n* `same_device` - same_device\n* `cross_device` - cross_device"
          }
        },
        "required": [
          "return_url"
        ]
      },
      "DigitalIdWalletApiMitidWalletVerificationStartCountryEnum": {
        "enum": [
          "DNK"
        ],
        "type": "string",
        "description": "* `DNK` - DNK"
      },
      "DigitalIdWalletApiWalletCatalogResponse": {
        "type": "object",
        "properties": {
          "wallets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DigitalIdWalletApiWalletCatalogEntry"
            }
          }
        },
        "required": [
          "wallets"
        ]
      },
      "DigitalIdWalletApiWalletCatalogEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "path": {
            "type": "string",
            "description": "L'endpoint propre au portefeuille pour le démarrage."
          },
          "countries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "issuing_authority": {
            "type": "string"
          },
          "level_of_assurance": {
            "type": "string",
            "nullable": true
          },
          "interaction": {
            "$ref": "#/components/schemas/DigitalIdWalletApiInteractionEnum"
          },
          "required_fields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "available": {
            "type": "boolean",
            "description": "Indique si cette application peut le lancer dans cet environnement dès maintenant. Être répertorié ne signifie pas être disponible en production."
          }
        },
        "required": [
          "available",
          "countries",
          "id",
          "interaction",
          "issuing_authority",
          "level_of_assurance",
          "name",
          "path",
          "required_fields"
        ]
      },
      "CaseDuplicateCaseDuplicate": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "case_number": {
            "type": "string",
            "nullable": true,
            "maxLength": 32
          },
          "title": {
            "type": "string",
            "maxLength": 255
          },
          "status": {
            "$ref": "#/components/schemas/CaseDuplicateStatusEnum"
          },
          "priority": {
            "$ref": "#/components/schemas/CaseDuplicatePriorityEnum"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "created_at",
          "title",
          "uuid"
        ]
      },
      "CaseDuplicateCaseDuplicatePage": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer"
          },
          "next_offset": {
            "type": "integer",
            "nullable": true
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseDuplicateCaseDuplicate"
            }
          }
        },
        "required": [
          "count",
          "next_offset",
          "results"
        ]
      },
      "RoutingPublicationPolicyDraftResponse": {
        "type": "object",
        "properties": {
          "draft": {
            "allOf": [
              {
                "$ref": "#/components/schemas/RoutingPublicationPolicyDraft"
              }
            ],
            "nullable": true
          }
        },
        "required": [
          "draft"
        ]
      },
      "RoutingPublicationPolicyDraftWriteRequest": {
        "type": "object",
        "properties": {
          "expected_version": {
            "type": "integer",
            "minimum": 0
          },
          "expected_revision": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "changes": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "required": [
          "changes",
          "expected_revision",
          "expected_version"
        ]
      },
      "CasePublicationPolicyDraft": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "string",
            "format": "uuid"
          },
          "base_version": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0
          },
          "changes": {},
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "maxLength": 254
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "base_version",
          "updated_at"
        ]
      },
      "CasePublicationPolicyDraftPreconditionRequest": {
        "type": "object",
        "properties": {
          "expected_version": {
            "type": "integer",
            "minimum": 0
          },
          "expected_revision": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        },
        "required": [
          "expected_revision",
          "expected_version"
        ]
      },
      "CaseCollaborationCaseNote": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "comment": {
            "type": "string"
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "maxLength": 255
          },
          "actor_name": {
            "type": "string",
            "nullable": true,
            "maxLength": 255
          },
          "mentioned_emails": {},
          "is_internal": {
            "type": "boolean"
          },
          "attachments": {},
          "tags": {},
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "reply_to": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CaseCollaborationCaseNoteReply"
              }
            ],
            "nullable": true,
            "readOnly": true
          },
          "is_pinned": {
            "type": "boolean"
          },
          "client_reference": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        },
        "required": [
          "comment",
          "created_at",
          "reply_to",
          "uuid"
        ]
      },
      "CustomerMessagingPaginatedCaseRequestList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?offset=400&limit=100"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?offset=200&limit=100"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerMessagingCaseRequest"
            }
          }
        }
      },
      "FraudCheckResponse": {
        "type": "object",
        "properties": {
          "check_id": {
            "type": "string",
            "format": "uuid"
          },
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Session de vérification native créée pour cette vérification."
          },
          "client_reference": {
            "type": "string",
            "nullable": true
          },
          "processing_status": {
            "$ref": "#/components/schemas/FraudProcessingStatusEnum"
          },
          "profile_id": {
            "type": "string"
          },
          "profile_version": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "inputs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FraudCheckInput"
            }
          },
          "modules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FraudCheckModuleReport"
            }
          },
          "attribute_evidence": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "compound_evidence": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "risk": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FraudCheckRisk"
            }
          },
          "network": {
            "type": "object",
            "additionalProperties": {}
          },
          "enrichment": {
            "type": "object",
            "additionalProperties": {}
          },
          "identity_relationship": {
            "allOf": [
              {
                "$ref": "#/components/schemas/FraudCheckIdentityRelationship"
              }
            ],
            "nullable": true
          },
          "recommendation": {
            "$ref": "#/components/schemas/FraudRecommendationEnum"
          },
          "next_action": {
            "$ref": "#/components/schemas/FraudNextActionEnum"
          },
          "decision_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "coverage": {
            "type": "object",
            "additionalProperties": {}
          },
          "usage": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "vendor_data": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "nullable": true
          }
        },
        "required": [
          "attribute_evidence",
          "check_id",
          "client_reference",
          "completed_at",
          "compound_evidence",
          "coverage",
          "created_at",
          "decision_reasons",
          "inputs",
          "modules",
          "network",
          "next_action",
          "processing_status",
          "profile_id",
          "profile_version",
          "recommendation",
          "risk",
          "usage"
        ]
      },
      "CaseReviewTeam": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseReviewTeamMember"
            },
            "maxItems": 250
          },
          "is_active": {
            "type": "boolean"
          },
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        }
      },
      "CaseActionCaseEntityActionRequest": {
        "type": "object",
        "properties": {
          "client_reference": {
            "type": "string",
            "format": "uuid"
          },
          "retry": {
            "type": "boolean",
            "default": false
          },
          "action": {
            "$ref": "#/components/schemas/CaseActionActionEnum"
          },
          "status": {
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            }
          },
          "note": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "action"
        ]
      },
      "RoutingPublicationPaginatedPolicyRevisionList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?offset=400&limit=100"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?offset=200&limit=100"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoutingPublicationPolicyRevision"
            }
          }
        }
      },
      "FraudRecommendationEnum": {
        "enum": [
          "approve",
          "review",
          "reject"
        ],
        "type": "string",
        "description": "* `approve` - Approuver\n* `review` - Examiner\n* `reject` - Rejeter"
      },
      "CustomerMessagingCaseRequestPreviewResponse": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "recipient": {
            "type": "string",
            "format": "email"
          },
          "sender": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "html": {
            "type": "string"
          },
          "requires_user_action": {
            "type": "boolean"
          },
          "preview_token": {
            "type": "string"
          }
        },
        "required": [
          "expires_at",
          "html",
          "preview_token",
          "recipient",
          "request_id",
          "requires_user_action",
          "sender",
          "subject"
        ]
      },
      "CustomerMessagingCaseCustomerResponseRequest": {
        "type": "object",
        "properties": {
          "full_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512
          },
          "date_of_birth": {
            "type": "string",
            "format": "date"
          },
          "file": {
            "type": "string",
            "format": "binary",
            "writeOnly": true
          }
        }
      },
      "CaseCollaborationCaseNoteReply": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "actor_name": {
            "type": "string",
            "nullable": true
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "comment": {
            "type": "string",
            "maxLength": 300
          }
        },
        "required": [
          "actor_email",
          "actor_name",
          "comment",
          "uuid"
        ]
      },
      "FraudCheckModuleReport": {
        "type": "object",
        "properties": {
          "module": {
            "$ref": "#/components/schemas/FraudExcludeEnum"
          },
          "status": {
            "$ref": "#/components/schemas/FraudStatusEnum"
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "latency_ms": {
            "type": "integer"
          },
          "freshness": {
            "type": "string",
            "nullable": true
          },
          "billable_units": {
            "type": "integer"
          }
        },
        "required": [
          "billable_units",
          "freshness",
          "latency_ms",
          "module",
          "reason",
          "status"
        ]
      },
      "CaseDuplicateEntityTypeEnum": {
        "enum": [
          "session",
          "business_session",
          "transaction"
        ],
        "type": "string",
        "description": "* `session` - Session\n* `business_session` - Session d'entreprise\n* `transaction` - Transaction"
      },
      "FraudClientCredentialsErrorMessage": {
        "type": "object",
        "properties": {
          "detail": {
            "type": "string",
            "default": "Authentication failed: Invalid client access token."
          }
        }
      },
      "FraudAvailabilityEnum": {
        "enum": [
          "available",
          "not_requested",
          "no_reference",
          "insufficient_history",
          "unsupported_region",
          "source_unavailable"
        ],
        "type": "string",
        "description": "* `available` - Disponible\n* `not_requested` - Non demandé\n* `no_reference` - Aucune référence\n* `insufficient_history` - Historique insuffisant\n* `unsupported_region` - Région non prise en charge\n* `source_unavailable` - Source indisponible"
      },
      "CasePublicationPolicyDraftResponse": {
        "type": "object",
        "properties": {
          "draft": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CasePublicationPolicyDraft"
              }
            ],
            "nullable": true
          }
        },
        "required": [
          "draft"
        ]
      },
      "FraudCheckAttributesRequest": {
        "type": "object",
        "description": "Attributs corroborants. Tous optionnels ; ils élargissent la couverture des modules.",
        "properties": {
          "first_name": {
            "type": "string",
            "maxLength": 128
          },
          "last_name": {
            "type": "string",
            "maxLength": 128
          },
          "full_name": {
            "type": "string",
            "maxLength": 256
          },
          "date_of_birth": {
            "type": "string",
            "format": "date"
          },
          "nationality": {
            "type": "string",
            "maxLength": 3
          },
          "gender": {
            "type": "string",
            "maxLength": 16
          },
          "address": {
            "type": "string",
            "maxLength": 512
          },
          "city": {
            "type": "string",
            "maxLength": 128
          },
          "state": {
            "type": "string",
            "maxLength": 128
          },
          "postal_code": {
            "type": "string",
            "maxLength": 32
          }
        }
      },
      "NetworkNote": {
        "type": "object",
        "required": [
          "uuid",
          "actor_email",
          "comment",
          "client_reference",
          "created_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "readOnly": true,
            "description": "Auteur authentifié, attribué par le serveur."
          },
          "comment": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000
          },
          "client_reference": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        }
      },
      "CaseActionEntityTypeEnum": {
        "enum": [
          "user",
          "business"
        ],
        "type": "string",
        "description": "* `user` - user\n* `business` - business"
      },
      "CaseRoutingCondition": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "source",
              "priority",
              "tags"
            ]
          },
          "operator": {
            "type": "string",
            "enum": [
              "equals",
              "in",
              "contains"
            ]
          },
          "value": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          }
        },
        "required": [
          "field",
          "operator",
          "value"
        ],
        "description": "Source et priority prennent en charge equals ou in avec les valeurs prises en charge. Tags prend en charge contains avec une seule balise non vide."
      },
      "RoutingPublicationPolicyRevision": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0
          },
          "snapshot": {},
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "maxLength": 254
          },
          "published_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "published_at",
          "snapshot",
          "version"
        ]
      },
      "CasePublicationPolicyRevision": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0
          },
          "snapshot": {},
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "maxLength": 254
          },
          "published_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "published_at",
          "snapshot",
          "version"
        ]
      },
      "FraudCheckIdentityRelationship": {
        "type": "object",
        "properties": {
          "result": {
            "$ref": "#/components/schemas/FraudResultEnum"
          },
          "reference_type": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "availability": {
            "$ref": "#/components/schemas/FraudAvailabilityEnum"
          },
          "reason_codes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "availability",
          "country",
          "reason_codes",
          "reference_type",
          "result"
        ]
      },
      "CasePublicationPaginatedPolicyRevisionList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?offset=400&limit=100"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?offset=200&limit=100"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CasePublicationPolicyRevision"
            }
          }
        }
      },
      "CaseDuplicateBlankEnum": {
        "enum": [
          ""
        ]
      },
      "FraudCheckPlan": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string"
          },
          "profile_version": {
            "type": "string"
          },
          "modules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FraudCheckPlannedModule"
            }
          },
          "estimated_price": {
            "type": "string",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "nullable": true
          },
          "is_sandbox": {
            "type": "boolean"
          },
          "can_afford": {
            "type": "boolean"
          }
        },
        "required": [
          "can_afford",
          "currency",
          "estimated_price",
          "is_sandbox",
          "modules",
          "profile_id",
          "profile_version"
        ]
      },
      "CaseReviewTeamUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseReviewTeamMember"
            },
            "maxItems": 250
          },
          "is_active": {
            "type": "boolean"
          }
        }
      },
      "RoutingPublicationPolicyDraft": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "string",
            "format": "uuid"
          },
          "base_version": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0
          },
          "changes": {},
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "maxLength": 254
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "base_version",
          "updated_at"
        ]
      },
      "FraudCheckRequestRequest": {
        "type": "object",
        "properties": {
          "client_reference": {
            "type": "string",
            "minLength": 1,
            "description": "Votre propre référence pour cette vérification. Fait également office de clé d'idempotence : la réutiliser avec le même corps de requête renvoie la vérification d'origine sans réexécuter ni refacturer les modules ; la réutiliser avec un corps différent renvoie une erreur 409.",
            "maxLength": 255
          },
          "profile": {
            "type": "string",
            "minLength": 1,
            "default": "standard",
            "description": "ID du profil d'orchestration. Le profil `standard` de Didit est utilisé par défaut.",
            "maxLength": 64
          },
          "profile_version": {
            "type": "string",
            "minLength": 1,
            "description": "Épingler une version de profil gelée. Correspond par défaut à la version actuelle du profil.",
            "maxLength": 32
          },
          "subject": {
            "$ref": "#/components/schemas/FraudCheckSubjectRequest"
          },
          "context": {
            "$ref": "#/components/schemas/FraudCheckContextRequest"
          },
          "checks": {
            "$ref": "#/components/schemas/FraudCheckModuleSelectionRequest"
          },
          "vendor_data": {
            "type": "string",
            "maxLength": 1000
          },
          "metadata": {}
        },
        "required": [
          "subject"
        ]
      },
      "CaseDuplicateCaseSubjectInputRequest": {
        "type": "object",
        "properties": {
          "type": {
            "$ref": "#/components/schemas/CaseDuplicateTypeEnum"
          },
          "uuid": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "type",
          "uuid"
        ]
      },
      "CaseReviewTeamMember": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "availability": {
            "type": "string",
            "enum": [
              "available",
              "unavailable"
            ],
            "default": "available"
          },
          "capacity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "default": 10
          },
          "skills": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 64
            },
            "maxItems": 25
          },
          "available_from": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "available_until": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "user_id"
        ]
      },
      "CaseRoutingPreviewRequest": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "MANUAL",
              "AML_SCREENING",
              "TRANSACTION_RULE",
              "WORKFLOW_BUILDER"
            ]
          },
          "priority": {
            "type": "string",
            "enum": [
              "LOW",
              "MEDIUM",
              "HIGH"
            ],
            "default": "MEDIUM"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 64
            },
            "maxItems": 50
          },
          "rule_uuid": {
            "type": "string",
            "format": "uuid"
          },
          "draft": {
            "$ref": "#/components/schemas/CaseRoutingRuleCreate"
          }
        },
        "required": [
          "source"
        ]
      },
      "FraudExcludeEnum": {
        "enum": [
          "normalization",
          "email_risk",
          "email_social",
          "phone_social",
          "phone_risk",
          "ip_risk",
          "database_validation",
          "networks_same_org",
          "networks_cross_org",
          "biometric_identity"
        ],
        "type": "string",
        "description": "* `normalization` - Normalisation\n* `email_risk` - Risque lié à l'e-mail\n* `email_social` - Réseaux sociaux de l'e-mail\n* `phone_social` - Réseaux sociaux du téléphone\n* `phone_risk` - Risque lié au téléphone\n* `ip_risk` - Risque lié à l'IP\n* `database_validation` - Validation en base de données\n* `networks_same_org` - Réseaux au sein de la même organisation\n* `networks_cross_org` - Réseaux inter-organisations\n* `biometric_identity` - Identité biométrique"
      },
      "CaseDuplicateCaseLinkCreateRequest": {
        "type": "object",
        "properties": {
          "entity_type": {
            "$ref": "#/components/schemas/CaseDuplicateEntityTypeEnum"
          },
          "entity_uuid": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "entity_type",
          "entity_uuid"
        ]
      },
      "CaseDuplicateStatusEnum": {
        "enum": [
          "OPEN",
          "AWAITING_USER",
          "RESOLVED"
        ],
        "type": "string",
        "description": "* `OPEN` - Ouvert\n* `AWAITING_USER` - En attente de l'utilisateur\n* `RESOLVED` - Résolu"
      },
      "FraudBandEnum": {
        "enum": [
          "low",
          "medium",
          "high",
          "unknown"
        ],
        "type": "string",
        "description": "* `low` - Faible\n* `medium` - Moyen\n* `high` - Élevé\n* `unknown` - Inconnu"
      },
      "CaseDuplicatePriorityEnum": {
        "enum": [
          "LOW",
          "MEDIUM",
          "HIGH"
        ],
        "type": "string",
        "description": "* `LOW` - Faible\n* `MEDIUM` - Moyen\n* `HIGH` - Élevé"
      },
      "FraudStatusEnum": {
        "enum": [
          "planned",
          "completed",
          "skipped",
          "failed"
        ],
        "type": "string",
        "description": "* `planned` - Planifié\n* `completed` - Terminé\n* `skipped` - Ignoré\n* `failed` - Échoué"
      },
      "FraudCheckInput": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "string",
            "description": "Identifiant masqué pour l'identifiant transmis."
          },
          "type": {
            "$ref": "#/components/schemas/FraudTypeEnum"
          },
          "namespace": {
            "type": "object",
            "additionalProperties": {}
          },
          "quality": {
            "type": "string"
          },
          "normalization": {
            "type": "object",
            "additionalProperties": {}
          },
          "availability": {
            "$ref": "#/components/schemas/FraudAvailabilityEnum"
          }
        },
        "required": [
          "availability",
          "namespace",
          "normalization",
          "quality",
          "reference",
          "type"
        ]
      },
      "CustomerMessagingPurposesEnum": {
        "enum": [
          "identity_document",
          "proof_of_address",
          "business_document",
          "confirm_details",
          "review_in_progress"
        ],
        "type": "string",
        "description": "* `identity_document` - identity_document\n* `proof_of_address` - proof_of_address\n* `business_document` - business_document\n* `confirm_details` - confirm_details\n* `review_in_progress` - review_in_progress"
      },
      "FraudTypeEnum": {
        "enum": [
          "email",
          "phone",
          "national_id",
          "tax_number",
          "passport_number",
          "driving_licence_number",
          "residence_permit_number",
          "voter_id",
          "external_id"
        ],
        "type": "string",
        "description": "* `email` - E-mail\n* `phone` - Téléphone\n* `national_id` - Identifiant national\n* `tax_number` - Identifiant fiscal\n* `passport_number` - Numéro de passeport\n* `driving_licence_number` - Numéro de permis de conduire\n* `residence_permit_number` - Numéro de titre de séjour\n* `voter_id` - Identifiant d'électeur\n* `external_id` - Identifiant externe"
      },
      "CaseDuplicateCaseSubjectInput": {
        "type": "object",
        "properties": {
          "type": {
            "$ref": "#/components/schemas/CaseDuplicateTypeEnum"
          },
          "uuid": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "type",
          "uuid"
        ]
      },
      "CaseReviewTeamCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseReviewTeamMember"
            },
            "maxItems": 250
          },
          "is_active": {
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "members"
        ]
      },
      "CaseDuplicateCaseDuplicateQueryRequest": {
        "type": "object",
        "properties": {
          "subject": {
            "$ref": "#/components/schemas/CaseDuplicateCaseSubjectInputRequest"
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseDuplicateCaseLinkCreateRequest"
            }
          },
          "offset": {
            "type": "integer",
            "maximum": 1000000,
            "minimum": 0,
            "default": 0
          }
        }
      },
      "CaseDuplicateResolutionEnum": {
        "enum": [
          "FALSE_POSITIVE",
          "VALID_THREAT"
        ],
        "type": "string",
        "description": "* `FALSE_POSITIVE` - Faux positif\n* `VALID_THREAT` - Menace avérée"
      },
      "CasePublicationPolicyDraftWriteRequest": {
        "type": "object",
        "properties": {
          "expected_version": {
            "type": "integer",
            "minimum": 0
          },
          "expected_revision": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "changes": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "required": [
          "changes",
          "expected_revision",
          "expected_version"
        ]
      },
      "FraudCheckSubjectRequest": {
        "type": "object",
        "properties": {
          "selfie": {
            "type": "string",
            "minLength": 1,
            "description": "Selfie au format JPEG, PNG ou WebP en Base64, jusqu'à 6 Mo. Aucune image de référence ni URL.",
            "maxLength": 8388672
          },
          "identifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FraudCheckIdentifierRequest"
            },
            "description": "Un ou plusieurs identifiants typés. Un seul suffit.",
            "maxItems": 10,
            "minItems": 1
          },
          "attributes": {
            "$ref": "#/components/schemas/FraudCheckAttributesRequest"
          }
        },
        "required": [
          "identifiers"
        ]
      },
      "RoutingPublicationRoutingCondition": {
        "type": "object",
        "properties": {
          "field": {
            "$ref": "#/components/schemas/RoutingPublicationFieldEnum"
          },
          "operator": {
            "$ref": "#/components/schemas/RoutingPublicationOperatorEnum"
          },
          "value": {}
        },
        "required": [
          "field",
          "operator",
          "value"
        ]
      },
      "CaseActionCaseActionReceipt": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "client_reference": {
            "type": "string",
            "format": "uuid"
          },
          "action": {
            "type": "string",
            "maxLength": 32
          },
          "status": {
            "$ref": "#/components/schemas/CaseActionStatusEnum"
          },
          "result": {},
          "error": {
            "type": "string",
            "maxLength": 255
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "maxLength": 254
          },
          "attempts": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "action",
          "client_reference",
          "created_at",
          "status",
          "updated_at",
          "uuid"
        ]
      },
      "FraudCheckContextRequest": {
        "type": "object",
        "properties": {
          "ip_address": {
            "type": "string",
            "minLength": 1
          },
          "user_agent": {
            "type": "string",
            "maxLength": 512
          },
          "country": {
            "type": "string",
            "description": "Pays dans lequel la personne déclare se trouver. Purement contextuel - ne constitue jamais une preuve de propriété de l'identité.",
            "maxLength": 3
          },
          "purpose": {
            "type": "string",
            "maxLength": 128
          },
          "consent_obtained": {
            "type": "boolean"
          }
        }
      },
      "CustomerMessagingCaseCustomerResponseResult": {
        "type": "object",
        "properties": {
          "responded_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "responded_at"
        ]
      },
      "CustomerMessagingCaseRequestContact": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "verified_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "email",
          "uuid",
          "verified_at"
        ]
      },
      "FraudClientCredentialsForbiddenErrorMessage": {
        "type": "object",
        "properties": {
          "detail": {
            "type": "string",
            "default": "Forbidden - User doesn't have permission"
          }
        }
      },
      "CasePublicationAssignmentMethodEnum": {
        "enum": [
          "MANUAL",
          "AUTOMATIC"
        ],
        "type": "string",
        "description": "* `MANUAL` - Manuel\n* `AUTOMATIC` - Automatique"
      },
      "CaseDuplicateNullEnum": {
        "enum": [
          null
        ]
      },
      "CustomerMessagingLanguageEnum": {
        "enum": [
          "en",
          "es",
          "pt"
        ],
        "type": "string",
        "description": "* `en` - en\n* `es` - es\n* `pt` - pt"
      },
      "CaseDuplicateCaseFraudSourceContextRequest": {
        "type": "object",
        "properties": {
          "check_id": {
            "type": "string",
            "format": "uuid"
          },
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "source_section": {
            "type": "string",
            "minLength": 1,
            "pattern": "^[A-Z][A-Z0-9_:-]{0,63}$"
          }
        },
        "required": [
          "check_id",
          "request_id",
          "source_section"
        ]
      },
      "FraudCheckPlannedModule": {
        "type": "object",
        "properties": {
          "module": {
            "$ref": "#/components/schemas/FraudExcludeEnum"
          },
          "available": {
            "type": "boolean"
          },
          "availability_reason": {
            "type": "string",
            "nullable": true
          },
          "will_run": {
            "type": "boolean"
          },
          "selection_reason": {
            "type": "string",
            "nullable": true
          },
          "estimated_price": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "availability_reason",
          "available",
          "estimated_price",
          "module",
          "selection_reason",
          "will_run"
        ]
      },
      "CustomerMessagingCaseRequestOptions": {
        "type": "object",
        "properties": {
          "contacts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerMessagingCaseRequestContact"
            }
          },
          "purposes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerMessagingPurposesEnum"
            }
          },
          "languages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerMessagingLanguagesEnum"
            }
          }
        },
        "required": [
          "contacts",
          "languages",
          "purposes"
        ]
      },
      "CaseCollaborationPaginatedCaseNoteList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?offset=400&limit=100"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?offset=200&limit=100"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseCollaborationCaseNote"
            }
          }
        }
      },
      "FraudProcessingStatusEnum": {
        "enum": [
          "pending",
          "running",
          "completed",
          "failed"
        ],
        "type": "string",
        "description": "* `pending` - En attente\n* `running` - En cours d'exécution\n* `completed` - Terminé\n* `failed` - Échoué"
      },
      "CasePublicationCaseBlueprint": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "name": {
            "type": "string",
            "maxLength": 24
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "assignment_method": {
            "$ref": "#/components/schemas/CasePublicationAssignmentMethodEnum"
          },
          "assignee_pool": {},
          "max_active_cases": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0,
            "nullable": true
          },
          "escalation_enabled": {
            "type": "boolean"
          },
          "escalation_blueprint": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "escalation_blueprint_name": {
            "type": "string",
            "readOnly": true
          },
          "transfer_enabled": {
            "type": "boolean"
          },
          "four_eyes_checker_blueprint": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "four_eyes_checker_blueprint_name": {
            "type": "string",
            "readOnly": true
          },
          "require_resolution_note": {
            "type": "boolean"
          },
          "content_config": {},
          "version": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0
          },
          "default_deadline_hours": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0,
            "nullable": true
          },
          "is_active": {
            "type": "boolean"
          },
          "preset_key": {
            "type": "string",
            "nullable": true,
            "maxLength": 64
          },
          "creation_sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            },
            "readOnly": true
          },
          "receives_escalation_from": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            },
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "created_at",
          "creation_sources",
          "escalation_blueprint_name",
          "four_eyes_checker_blueprint_name",
          "name",
          "receives_escalation_from",
          "updated_at",
          "uuid"
        ]
      },
      "CaseRoutingRuleUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "priority": {
            "type": "integer",
            "minimum": 0
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseRoutingCondition"
            },
            "maxItems": 20
          },
          "required_skills": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 64
            },
            "maxItems": 25
          },
          "blueprint": {
            "type": "string",
            "format": "uuid"
          },
          "team": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "is_active": {
            "type": "boolean"
          },
          "expected_version": {
            "type": "integer",
            "minimum": 1,
            "writeOnly": true,
            "description": "Version ouverte par l'éditeur. Lorsqu'elle est fournie, les écritures obsolètes renvoient 409 sans modifier la règle."
          }
        }
      },
      "CustomerMessagingCaseRequestPreviewRequest": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "purpose": {
            "$ref": "#/components/schemas/CustomerMessagingPurposeEnum"
          },
          "language": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CustomerMessagingLanguageEnum"
              }
            ],
            "default": "en"
          }
        },
        "required": [
          "contact_id",
          "purpose"
        ]
      },
      "CaseDuplicateCaseFraudSourceContext": {
        "type": "object",
        "properties": {
          "check_id": {
            "type": "string",
            "format": "uuid"
          },
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "source_section": {
            "type": "string",
            "pattern": "^[A-Z][A-Z0-9_:-]{0,63}$"
          }
        },
        "required": [
          "check_id",
          "request_id",
          "source_section"
        ]
      },
      "RoutingPublicationOperatorEnum": {
        "enum": [
          "equals",
          "in",
          "contains"
        ],
        "type": "string",
        "description": "* `equals` - equals\n* `in` - in\n* `contains` - contains"
      },
      "CaseRoutingPreview": {
        "type": "object",
        "properties": {
          "rule_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "rule_name": {
            "type": "string",
            "nullable": true
          },
          "rule_version": {
            "type": "integer",
            "nullable": true
          },
          "blueprint_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "team_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "assignee_user_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "reason": {
            "type": "string"
          },
          "candidates": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "user_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "eligible": {
                  "type": "boolean"
                },
                "active_cases": {
                  "type": "integer",
                  "nullable": true
                },
                "reason": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "matched_rules": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "priority": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "FraudDimensionEnum": {
        "enum": [
          "identity",
          "contact",
          "device_network",
          "behavioral",
          "fraud_network"
        ],
        "type": "string",
        "description": "* `identity` - Identité\n* `contact` - Contact\n* `device_network` - Réseau de l'appareil\n* `behavioral` - Comportemental\n* `fraud_network` - Réseau de fraude"
      },
      "FraudBadRequestErrorMessage": {
        "type": "object",
        "properties": {
          "detail": {
            "type": "string",
            "default": "Bad Request - Invalid request data"
          }
        }
      },
      "FraudNextActionEnum": {
        "enum": [
          "none",
          "manual_review",
          "step_up",
          "resubmit_capture"
        ],
        "type": "string",
        "description": "* `none` - Aucun\n* `manual_review` - Examen manuel\n* `step_up` - Vérification renforcée\n* `resubmit_capture` - Resoumettre la capture"
      },
      "RoutingPublicationPolicyDraftPreconditionRequest": {
        "type": "object",
        "properties": {
          "expected_version": {
            "type": "integer",
            "minimum": 0
          },
          "expected_revision": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        },
        "required": [
          "expected_revision",
          "expected_version"
        ]
      },
      "FraudCheckRisk": {
        "type": "object",
        "properties": {
          "dimension": {
            "$ref": "#/components/schemas/FraudDimensionEnum"
          },
          "score": {
            "type": "integer",
            "nullable": true
          },
          "band": {
            "$ref": "#/components/schemas/FraudBandEnum"
          },
          "availability": {
            "$ref": "#/components/schemas/FraudAvailabilityEnum"
          },
          "requested_but_unavailable": {
            "type": "boolean",
            "description": "Vrai lorsque la requête a fourni tout ce dont cette dimension avait besoin et que la plateforme n'a tout de même pas pu y répondre. Une telle vérification n'est jamais recommandée pour approbation sur la seule base des dimensions ayant répondu."
          },
          "reason_codes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "evidence_indexes": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          }
        },
        "required": [
          "availability",
          "band",
          "dimension",
          "evidence_indexes",
          "reason_codes",
          "requested_but_unavailable",
          "score"
        ]
      },
      "CaseDuplicateSourceEnum": {
        "enum": [
          "MANUAL",
          "AML_SCREENING",
          "TRANSACTION_RULE",
          "WORKFLOW_BUILDER"
        ],
        "type": "string",
        "description": "* `MANUAL` - Manuel\n* `AML_SCREENING` - Filtrage AML\n* `TRANSACTION_RULE` - Règle de transaction\n* `WORKFLOW_BUILDER` - Générateur de workflow"
      },
      "CaseCollaborationPatchedCaseNoteUpdateRequest": {
        "type": "object",
        "properties": {
          "is_pinned": {
            "type": "boolean"
          }
        }
      },
      "CustomerMessagingPurposeEnum": {
        "enum": [
          "identity_document",
          "proof_of_address",
          "business_document",
          "confirm_details",
          "review_in_progress"
        ],
        "type": "string",
        "description": "* `identity_document` - identity_document\n* `proof_of_address` - proof_of_address\n* `business_document` - business_document\n* `confirm_details` - confirm_details\n* `review_in_progress` - review_in_progress"
      },
      "CaseDuplicateTypeEnum": {
        "enum": [
          "user",
          "business"
        ],
        "type": "string",
        "description": "* `user` - user\n* `business` - business"
      },
      "CaseCollaborationCaseNoteCreateRequest": {
        "type": "object",
        "properties": {
          "comment": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000
          },
          "reply_to": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "client_reference": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "mentioned_emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email",
              "minLength": 1
            }
          },
          "is_internal": {
            "type": "boolean",
            "default": false
          },
          "attachments": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            }
          }
        },
        "required": [
          "comment"
        ]
      },
      "CustomerMessagingLanguagesEnum": {
        "enum": [
          "en",
          "es",
          "pt"
        ],
        "type": "string",
        "description": "* `en` - en\n* `es` - es\n* `pt` - pt"
      },
      "CustomerMessagingCaseRequestConfirmRequest": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "purpose": {
            "$ref": "#/components/schemas/CustomerMessagingPurposeEnum"
          },
          "language": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CustomerMessagingLanguageEnum"
              }
            ],
            "default": "en"
          },
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "preview_token": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512
          }
        },
        "required": [
          "contact_id",
          "expires_at",
          "preview_token",
          "purpose",
          "request_id"
        ]
      },
      "CaseRoutingRule": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "priority": {
            "type": "integer",
            "minimum": 0
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseRoutingCondition"
            },
            "maxItems": 20
          },
          "required_skills": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 64
            },
            "maxItems": 25
          },
          "blueprint": {
            "type": "string",
            "format": "uuid"
          },
          "team": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "is_active": {
            "type": "boolean"
          },
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "version": {
            "type": "integer",
            "readOnly": true
          },
          "blueprint_name": {
            "type": "string",
            "readOnly": true
          },
          "team_name": {
            "type": "string",
            "nullable": true,
            "readOnly": true
          }
        }
      },
      "FraudResultEnum": {
        "enum": [
          "match",
          "mismatch",
          "inconclusive",
          "no_reference"
        ],
        "type": "string",
        "description": "* `match` - Correspondance\n* `mismatch` - Non-correspondance\n* `inconclusive` - Non concluant\n* `no_reference` - Aucune référence"
      },
      "CaseRoutingRuleCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "priority": {
            "type": "integer",
            "minimum": 0
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseRoutingCondition"
            },
            "maxItems": 20
          },
          "required_skills": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 64
            },
            "maxItems": 25
          },
          "blueprint": {
            "type": "string",
            "format": "uuid"
          },
          "team": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "is_active": {
            "type": "boolean"
          },
          "publish": {
            "type": "boolean",
            "writeOnly": true,
            "description": "Définissez sur false pour enregistrer un brouillon jamais publié. L'enregistrement reste inactif à la version 0 jusqu'à ce que le brouillon soit explicitement publié. L'omission de ce champ préserve la création immédiate pour les intégrations existantes."
          }
        },
        "required": [
          "name",
          "conditions",
          "blueprint"
        ]
      },
      "FraudCheckIdentifierRequest": {
        "type": "object",
        "properties": {
          "type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/FraudTypeEnum"
              }
            ],
            "description": "Type d'identifiant. Détermine quels champs de namespace sont requis.\n\n* `email` - Email\n* `phone` - Téléphone\n* `national_id` - Identifiant national\n* `tax_number` - Numéro fiscal\n* `passport_number` - Numéro de passeport\n* `driving_licence_number` - Numéro de permis de conduire\n* `residence_permit_number` - Numéro de titre de séjour\n* `voter_id` - Carte d'électeur\n* `external_id` - Identifiant externe"
          },
          "value": {
            "type": "string",
            "minLength": 1,
            "description": "La valeur de l'identifiant, dans tout format habituel.",
            "maxLength": 255
          },
          "country": {
            "type": "string",
            "description": "Pays de délivrance ISO-3166 alpha-2 ou alpha-3. Requis pour les types d'identifiants gouvernementaux : les mêmes chiffres correspondent à des personnes différentes selon les pays.",
            "maxLength": 3
          },
          "issuer": {
            "type": "string",
            "description": "Autorité de délivrance ou émetteur infranational optionnel, lorsque le pays seul n'est pas unique.",
            "maxLength": 128
          }
        },
        "required": [
          "type",
          "value"
        ]
      },
      "CaseActionActionEnum": {
        "enum": [
          "set_status",
          "add_tags",
          "add_note",
          "add_to_blocklist"
        ],
        "type": "string",
        "description": "* `set_status` - set_status\n* `add_tags` - add_tags\n* `add_note` - add_note\n* `add_to_blocklist` - add_to_blocklist"
      },
      "CaseActionCaseActionReceiptPage": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer"
          },
          "next_offset": {
            "type": "integer",
            "nullable": true
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaseActionCaseActionReceipt"
            }
          }
        },
        "required": [
          "count",
          "next_offset",
          "results"
        ]
      },
      "CaseActionCaseEntityActionResult": {
        "type": "object",
        "properties": {
          "receipt": {
            "$ref": "#/components/schemas/CaseActionCaseActionReceipt"
          },
          "entity_type": {
            "$ref": "#/components/schemas/CaseActionEntityTypeEnum"
          },
          "entity_uuid": {
            "type": "string",
            "format": "uuid"
          },
          "action": {
            "type": "string"
          },
          "previous_status": {
            "type": "string"
          },
          "new_status": {
            "type": "string"
          },
          "tags_added": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "comment_uuid": {
            "type": "string",
            "format": "uuid"
          },
          "blocklisted": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CustomerMessagingCaseRequest": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "purpose": {
            "type": "string",
            "readOnly": true
          },
          "language": {
            "type": "string",
            "readOnly": true
          },
          "recipient": {
            "type": "string",
            "format": "email",
            "readOnly": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "readOnly": true,
            "nullable": true
          },
          "delivery_status": {
            "type": "string",
            "readOnly": true
          },
          "delivered_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "nullable": true
          },
          "cancelled_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "nullable": true
          },
          "responded_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "nullable": true
          },
          "response": {
            "readOnly": true,
            "nullable": true
          },
          "has_attachment": {
            "type": "boolean",
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "actor_email",
          "cancelled_at",
          "created_at",
          "delivered_at",
          "delivery_status",
          "expires_at",
          "has_attachment",
          "language",
          "purpose",
          "recipient",
          "responded_at",
          "response",
          "uuid"
        ]
      },
      "CustomerMessagingCaseRequestPublic": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "purpose": {
            "$ref": "#/components/schemas/CustomerMessagingPurposeEnum"
          },
          "language": {
            "$ref": "#/components/schemas/CustomerMessagingLanguageEnum"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "responded_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "copy": {
            "type": "object",
            "additionalProperties": {}
          },
          "organization_name": {
            "type": "string"
          },
          "is_white_label": {
            "type": "boolean"
          },
          "customization": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true
          }
        },
        "required": [
          "copy",
          "customization",
          "expires_at",
          "is_white_label",
          "language",
          "organization_name",
          "purpose",
          "request_id",
          "responded_at"
        ]
      },
      "RoutingPublicationFieldEnum": {
        "enum": [
          "source",
          "priority",
          "tags"
        ],
        "type": "string",
        "description": "* `source` - source\n* `priority` - priority\n* `tags` - tags"
      },
      "RoutingPublicationCaseRoutingRule": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "priority": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": 0
          },
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoutingPublicationRoutingCondition"
            }
          },
          "required_skills": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 64
            },
            "maxItems": 25
          },
          "blueprint": {
            "type": "string",
            "format": "uuid"
          },
          "blueprint_name": {
            "type": "string",
            "readOnly": true
          },
          "team": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "team_name": {
            "type": "string",
            "readOnly": true
          },
          "is_active": {
            "type": "boolean"
          },
          "version": {
            "type": "integer",
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "blueprint",
          "blueprint_name",
          "conditions",
          "created_at",
          "name",
          "team_name",
          "updated_at",
          "uuid",
          "version"
        ]
      },
      "CaseActionStatusEnum": {
        "enum": [
          "APPLIED",
          "FAILED"
        ],
        "type": "string",
        "description": "* `APPLIED` - Appliqué\n* `FAILED` - Échoué"
      },
      "FraudCheckModuleSelectionRequest": {
        "type": "object",
        "properties": {
          "include": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FraudExcludeEnum"
            }
          },
          "exclude": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FraudExcludeEnum"
            }
          }
        }
      },
      "SignatureField": {
        "type": "object",
        "description": "Un champ à placer sur un document de session : quel signataire le remplit, comment et où. Indiquez soit une position (`page`, `x`, `y`, `width` et `height`), soit un `anchor`. Les positions sont des fractions de la page telle qu'elle est affichée, depuis son coin supérieur gauche, arrondies à 4 décimales, et le champ doit s'insérer dans la page. Un document accepte jusqu'à 200 champs et un signataire jusqu'à 500, et chaque rôle ayant des champs sur un document nécessite un champ `signature` ou `initials` sur celui-ci. Consultez [Champs sur le document](/fr/core-technology/electronic-signature/overview#champs-sur-le-document).",
        "required": [
          "key",
          "type"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{0,63}$",
            "description": "Indique le nom du champ dans les résultats et dans `sign.field_values`. Unique au sein du document."
          },
          "type": {
            "type": "string",
            "enum": [
              "signature",
              "initials",
              "full_name",
              "date_signed",
              "text",
              "checkbox",
              "email",
              "data"
            ],
            "description": "Le contenu du champ. Le signataire applique sa `signature` et ses `initials` adoptées, saisit du texte dans un champ `text`, coche une case `checkbox` et saisit une adresse e-mail dans un champ `email` lorsque la session ne comporte aucun e-mail vérifié. Didit renseigne `full_name` (le nom vérifié), `date_signed` (la date de signature, dans le fuseau horaire du signataire), `data` (issu de `prefill`) ainsi qu'un `email` vérifié, et les affiche en lecture seule. Il n'existe pas de type sélecteur de date : utilisez `text`."
          },
          "role": {
            "type": "string",
            "enum": [
              "verified_person",
              "legal_representative",
              "key_people"
            ],
            "description": "Qui remplit le champ, avec les valeurs `signature_signer`. Une étape ne remplit et n'estampille que les champs de son propre signataire. Vaut par défaut le signataire de l'étape."
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "description": "Numéro de page, de 1 au nombre total de pages du document. Pour un document Word, page du PDF converti."
          },
          "x": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Bord gauche, sous forme de fraction de la largeur de la page."
          },
          "y": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Bord supérieur, sous forme de fraction de la hauteur de la page."
          },
          "width": {
            "type": "number",
            "minimum": 0.02,
            "maximum": 1,
            "description": "Largeur, exprimée en fraction de la largeur de la page. Une signature a une largeur d'au moins `0.12`."
          },
          "height": {
            "type": "number",
            "minimum": 0.012,
            "maximum": 1,
            "description": "Hauteur, sous forme de fraction de la hauteur de la page. Une signature a une hauteur minimale de `0.035`."
          },
          "anchor": {
            "$ref": "#/components/schemas/SignatureFieldAnchor"
          },
          "required": {
            "type": "boolean",
            "description": "`signature` and `initials` are required unless you set `false`. `full_name`, `date_signed` and `data` are always required. The signer can't finish a document until its required fields have a value, and a required checkbox must be ticked."
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "Affiché au signataire et dans les résultats. Défini par défaut à partir du type."
          },
          "placeholder": {
            "type": "string",
            "nullable": true,
            "maxLength": 80,
            "description": "`text` et `email` uniquement."
          },
          "validation": {
            "$ref": "#/components/schemas/SignatureFieldValidation"
          },
          "prefill": {
            "type": "string",
            "nullable": true,
            "description": "Provenance de la valeur : `identity.full_name`, `identity.first_name`, `identity.last_name`, `identity.date_of_birth` (`DD/MM/YYYY`), `identity.nationality`, `identity.document_number`, `identity.document_type`, `identity.issuing_country`, `identity.address`, `contact.email`, `contact.phone`, `company.name`, `company.registration_number`, `company.address`, `company.country` (KYB), `session.vendor_data`, `metadata.<key>` (une clé des `metadata` de la session) ou `api.<key>` (une clé de `sign.field_values`). Requis pour `data`. `full_name` utilise toujours `identity.full_name` et `email` utilise `contact.email`. Les valeurs des champs `data`, `full_name` et `email` vérifié sont figées dès que le signataire commence à signer."
          },
          "editable_when_prefilled": {
            "type": "boolean",
            "default": false,
            "description": "`text` et `email` uniquement : le signataire peut modifier une valeur préremplie."
          },
          "checked_by_default": {
            "type": "boolean",
            "default": false,
            "description": "`checkbox` uniquement : la case est initialement cochée."
          },
          "date_format": {
            "type": "string",
            "enum": [
              "DD/MM/YYYY",
              "MM/DD/YYYY",
              "YYYY-MM-DD",
              "D MMMM YYYY"
            ],
            "default": "DD/MM/YYYY",
            "description": "`date_signed` uniquement."
          }
        }
      },
      "SessionSignDocument": {
        "type": "object",
        "required": [
          "file_name",
          "content_base64"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Titre affiché au signataire. Prend la valeur par défaut `file_name`."
          },
          "file_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Nom de fichier, se terminant par `.pdf` ou `.docx`."
          },
          "content_base64": {
            "type": "string",
            "format": "byte",
            "description": "Le fichier, encodé en base64. Un PDF peut faire jusqu'à 20 MB et 100 pages, sans mot de passe, scripts ou fichiers joints. Un fichier Word (`.docx`) peut faire jusqu'à 20 MB et est converti en PDF pendant l'exécution de la requête, en 25 secondes au maximum ; le PDF a ensuite les mêmes limites. Jusqu'à 5 fichiers Word par session. Un fichier Word contenant des macros, des modifications suivies, des liens vers du contenu externe ou des objets incorporés est refusé avec `signature_document_not_supported`, et un fichier qui ne peut pas être converti renvoie `signature_document_conversion_failed`, chacun avec une `reason`."
          },
          "fields": {
            "type": "array",
            "description": "Champs optionnels à placer sur ce document, jusqu'à 200. Les pages et les positions font référence au PDF, ou au PDF converti pour un fichier Word. Sans champs, le signataire lit le document et l'accepte.",
            "items": {
              "$ref": "#/components/schemas/SignatureField"
            },
            "maxItems": 200
          }
        }
      },
      "SignatureResult": {
        "type": "object",
        "description": "Le résultat d'un signataire pour une étape de Signature électronique. Consultez le [rapport de Signature électronique](/fr/core-technology/electronic-signature/report-electronic-signature).",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Transmettez-le comme `signature_id` pour télécharger les preuves de ce signataire ou valider sa signature."
          },
          "node_id": {
            "type": "string",
            "description": "L'étape de workflow qui l'a produit."
          },
          "status": {
            "type": "string",
            "enum": [
              "intro",
              "review",
              "code",
              "signing",
              "signed",
              "declined"
            ],
            "description": "Statut du signataire dans l'étape. Seul `signed` signifie que les documents sont signés."
          },
          "verdict": {
            "type": "string",
            "enum": [
              "Not Finished",
              "Approved",
              "In Review",
              "Declined"
            ],
            "description": "Le résultat de l'étape. Un avertissement le définit via sa règle ; les règles de statut personnalisées s'appliquent ensuite."
          },
          "level": {
            "type": "string",
            "enum": [
              "simple",
              "aes",
              "qes"
            ],
            "description": "`simple` (par défaut) ou `aes`. `qes` (signature électronique qualifiée, SEQ) est un module complémentaire qui n'est pas encore disponible."
          },
          "format": {
            "type": "string",
            "enum": [
              "pdf",
              "pades"
            ],
            "description": "`pdf` pour une signature Simple, `pades` pour une signature Avancée (AES)."
          },
          "profile": {
            "type": "string",
            "nullable": true,
            "description": "`PAdES-B-LT` une fois qu'une signature avancée (AES) est apposée, sinon null."
          },
          "signer": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "nullable": true,
                "description": "Le nom du signataire. Vérifié (à partir de la vérification d'identité approuvée ou de la session), sauf au niveau Simple sans nom de session vérifié, où il s'agit du nom saisi par le signataire et il n'est pas vérifié."
              },
              "capacity": {
                "type": "string",
                "enum": [
                  "self",
                  "company"
                ]
              },
              "company": {
                "type": "string",
                "nullable": true
              },
              "role": {
                "type": "string",
                "nullable": true,
                "description": "La désignation de la personne clé, telle que déclarée."
              },
              "roles": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Les rôles structurés de la personne clé, tels que déclarés pour l'entreprise."
              },
              "identity_session_id": {
                "type": "string",
                "format": "uuid",
                "description": "La session KYC qui a vérifié le signataire."
              }
            }
          },
          "identity_used": {
            "type": "object",
            "description": "L'identité vérifiée sur laquelle repose la signature. Vide pour une signature simple sans identité vérifiée.",
            "properties": {
              "session_id": {
                "type": "string",
                "format": "uuid"
              },
              "kyc_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true
              },
              "verified": {
                "type": "boolean"
              },
              "expected_name": {
                "type": "string",
                "nullable": true,
                "description": "Le nom auquel le signataire devait correspondre."
              }
            }
          },
          "certificate": {
            "type": "object",
            "nullable": true,
            "description": "Le certificat avec lequel les documents ont été signés. `null` jusqu'à la signature, et toujours `null` pour une signature Simple.",
            "properties": {
              "issuer": {
                "type": "string"
              },
              "issued_to": {
                "type": "string"
              },
              "serial": {
                "type": "string",
                "description": "Numéro de série, hexadécimal."
              },
              "valid_from": {
                "type": "string",
                "format": "date-time"
              },
              "valid_until": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "confirmation": {
            "type": "object",
            "properties": {
              "channel": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "email",
                  "sms"
                ],
                "description": "`null` pour une signature Simple, qui ne comporte aucun code."
              },
              "destination": {
                "type": "string",
                "nullable": true,
                "description": "Le contact masqué auquel le code a été envoyé."
              },
              "confirmed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "attempts": {
                "type": "integer",
                "description": "Codes saisis, dont le bon."
              }
            }
          },
          "timestamp": {
            "type": "object",
            "nullable": true,
            "description": "L'horodatage RFC 3161 dans la signature, émis par Didit. `null` jusqu'à la signature, et toujours `null` pour une signature simple.",
            "properties": {
              "time": {
                "type": "string",
                "format": "date-time"
              },
              "qualified": {
                "type": "boolean",
                "description": "Toujours `false` pour l'AES."
              },
              "valid": {
                "type": "boolean"
              }
            }
          },
          "documents": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Le document présent sur la copie de ce signataire. Utilisez-le pour télécharger le fichier signé."
                },
                "uuid": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Identique à `id`."
                },
                "title": {
                  "type": "string"
                },
                "file_name": {
                  "type": "string"
                },
                "pages": {
                  "type": "integer",
                  "description": "Pages du document signé. Pour Word, du PDF converti."
                },
                "size_bytes": {
                  "type": "integer"
                },
                "sha256_original": {
                  "type": "string",
                  "description": "SHA-256 du document tel qu'il a été présenté au signataire."
                },
                "sha256_signed": {
                  "type": "string",
                  "nullable": true,
                  "description": "SHA-256 du PDF signé, une fois signé."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "signed",
                    "declined",
                    "not_signed",
                    "not_reached"
                  ],
                  "description": "`not_signed` : ouvert mais non signé. `not_reached` : jamais ouvert."
                },
                "opened_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                },
                "read_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true,
                  "description": "Moment où le signataire a atteint la fin d'un document sans champs, lorsque l'étape l'exige."
                },
                "read_to_end": {
                  "type": "boolean"
                },
                "consented_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true,
                  "description": "Moment où le signataire a accepté un document sans champs, ou a complété les champs d'un document comportant des champs."
                },
                "consent": {
                  "type": "boolean"
                },
                "signed_file": {
                  "type": "string",
                  "nullable": true,
                  "description": "Chemin du PDF signé, une fois signé. Voir [Télécharger un document signé](/fr/sessions-api/electronic-signature/download-signed-document)."
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "fields",
                    "read_and_agree"
                  ],
                  "description": "`fields` pour un document avec des champs, `read_and_agree` pour un document sans champs."
                },
                "source_format": {
                  "type": "string",
                  "enum": [
                    "pdf",
                    "docx"
                  ],
                  "description": "`pdf`, ou `docx` pour un document Word que Didit a converti en PDF."
                },
                "conversion": {
                  "type": "object",
                  "nullable": true,
                  "description": "`null` pour un PDF. Pour un document Word, le fichier d'origine et la conversion.",
                  "properties": {
                    "from": {
                      "type": "string",
                      "enum": [
                        "docx"
                      ]
                    },
                    "file_name": {
                      "type": "string",
                      "description": "Le nom d'origine de votre fichier Word."
                    },
                    "sha256": {
                      "type": "string",
                      "description": "SHA-256 de votre fichier Word d'origine."
                    },
                    "size_bytes": {
                      "type": "integer",
                      "description": "Taille de votre fichier Word d'origine."
                    },
                    "converter": {
                      "type": "string",
                      "description": "Version du convertisseur qui a produit le PDF."
                    }
                  }
                },
                "fields": {
                  "type": "array",
                  "description": "Champs sur le document, avec leurs valeurs. Vide pour un document sans champs.",
                  "items": {
                    "$ref": "#/components/schemas/SignatureFieldResult"
                  }
                }
              }
            }
          },
          "adopted_signature": {
            "type": "object",
            "nullable": true,
            "description": "La signature et les initiales adoptées par le signataire pour les champs de signature et d'initiales. Vaut `null` tant que le signataire n'en a pas adopté.",
            "properties": {
              "method": {
                "type": "string",
                "enum": [
                  "typed",
                  "drawn"
                ],
                "description": "`typed` : le nom vérifié dans un style manuscrit. `drawn` : dessiné avec un doigt ou une souris."
              },
              "font": {
                "type": "string",
                "nullable": true,
                "description": "Le style d'écriture manuscrite d'une signature tapée. `null` lorsqu'elle est dessinée."
              },
              "adopted_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "electronic_signature_consent_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où le signataire a accepté, sur l'écran d'examen, de signer électroniquement les documents. Défini lorsqu'un document comporte des champs."
          },
          "evidence_file": {
            "type": "string",
            "nullable": true,
            "description": "Chemin d'accès au PDF de preuve, une fois signé. Voir [Télécharger les preuves de signature](/fr/sessions-api/electronic-signature/download-evidence)."
          },
          "warnings": {
            "type": "array",
            "description": "Avertissements générés pour ce signataire. Voir [Avertissements de la signature électronique](/fr/core-technology/electronic-signature/warnings-electronic-signature).",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "SIGNATURE_DECLINED",
                    "SIGNATURE_OTP_FAILED",
                    "SIGNATURE_NAME_MISMATCH",
                    "SIGNATURE_IDENTITY_NOT_VERIFIED",
                    "SIGNATURE_DOCUMENT_CHANGED",
                    "SIGNATURE_FIELD_DATA_MISSING"
                  ]
                },
                "node_id": {
                  "type": "string"
                }
              }
            }
          },
          "validation": {
            "type": "object",
            "nullable": true,
            "description": "La dernière vérification cryptographique des documents signés. `null` jusqu'à ce que les documents soient signés. Si Didit ne peut pas confirmer l'issue de la signature, la valeur est `{\"valid\": null, \"reason\": \"signature_provider_outcome_unknown\", \"checked_at\": ...}` et `status` reste à `signing` : traitez-le comme non signé.",
            "properties": {
              "valid": {
                "type": "boolean",
                "nullable": true,
                "description": "`true` lorsque chaque document est valide. `null` lorsque le résultat de la signature n'a pas pu être confirmé."
              },
              "reason": {
                "type": "string",
                "description": "Défini lorsque `valid` est `null` : `signature_provider_outcome_unknown`."
              },
              "checked_at": {
                "type": "string",
                "format": "date-time"
              },
              "documents": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "checked_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "valid": {
                      "type": "boolean",
                      "description": "`true` lorsque la signature et l'horodatage sont tous deux valides et de confiance."
                    },
                    "integrity": {
                      "type": "boolean",
                      "description": "`true` lorsque le document n'a pas été modifié depuis sa signature."
                    },
                    "trusted": {
                      "type": "boolean",
                      "description": "`true` lorsque le certificat de signature remonte à une racine de confiance."
                    },
                    "revoked": {
                      "type": "boolean"
                    },
                    "trusted_list": {
                      "type": "object",
                      "description": "Vérification de la liste de confiance de l'UE. Pour AES : `{\"status\": \"not_applicable\", \"reason\": \"aes_not_qualified\"}`.",
                      "properties": {
                        "status": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string"
                        }
                      }
                    },
                    "certificate": {
                      "type": "object",
                      "nullable": true,
                      "description": "Le certificat avec lequel les documents ont été signés. `null` jusqu'à la signature, et toujours `null` pour une signature Simple.",
                      "properties": {
                        "issuer": {
                          "type": "string"
                        },
                        "issued_to": {
                          "type": "string"
                        },
                        "serial": {
                          "type": "string",
                          "description": "Numéro de série, hexadécimal."
                        },
                        "valid_from": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "valid_until": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    },
                    "timestamp": {
                      "type": "object",
                      "nullable": true,
                      "description": "L'horodatage RFC 3161 dans la signature, émis par Didit. `null` jusqu'à la signature, et toujours `null` pour une signature simple.",
                      "properties": {
                        "time": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "qualified": {
                          "type": "boolean",
                          "description": "Toujours `false` pour l'AES."
                        },
                        "valid": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "declined_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "declined_action": {
            "type": "string",
            "enum": [
              "DECLINE",
              "REVIEW",
              "NO_ACTION"
            ]
          },
          "signed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où le lien de signature cesse de fonctionner."
          },
          "email_sent_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "email_unavailable_reason": {
            "type": "string",
            "nullable": true
          },
          "ip_address": {
            "type": "string",
            "nullable": true,
            "description": "L'adresse IP du signataire au moment où il a demandé son code."
          },
          "place": {
            "type": "string",
            "nullable": true,
            "description": "Non collecté : toujours `null`."
          },
          "place_unavailable_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "not_collected"
            ]
          }
        }
      },
      "SignatureFieldValidation": {
        "type": "object",
        "nullable": true,
        "description": "Règles applicables à la valeur d'un champ `text`. La prévisualisation dans la console, le flux de signature et l'API appliquent les mêmes règles.",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "any",
              "letters",
              "number",
              "email",
              "pattern"
            ],
            "description": "`letters` : lettres dans tout système d'écriture, espaces, traits d'union et apostrophes. `number` : chiffres avec un séparateur décimal facultatif. `pattern` : la valeur doit correspondre à `pattern`."
          },
          "min_length": {
            "type": "integer",
            "minimum": 0,
            "maximum": 500,
            "description": "De `0` jusqu'à `max_length`."
          },
          "max_length": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 120
          },
          "pattern": {
            "type": "string",
            "nullable": true,
            "minLength": 1,
            "maxLength": 200,
            "description": "Requis avec `kind: \"pattern\"`. Une expression régulière à laquelle la valeur entière doit correspondre. Les assertions avant/arrière (lookarounds) et les références arrière ne sont pas prises en charge."
          },
          "message": {
            "type": "string",
            "nullable": true,
            "maxLength": 120,
            "description": "Affiché au signataire à la place de l'erreur par défaut."
          }
        }
      },
      "SignatureFieldAnchor": {
        "type": "object",
        "description": "Positionne un champ d'après un extrait de texte dans le document plutôt que par des coordonnées. Didit ne supprime pas le texte du PDF, écrivez-le donc de la même couleur que l'arrière-plan de la page. Si le texte n'est pas trouvé, l'appel renvoie `400` avec `field_anchor_not_found`. Voir [Positionner des champs par texte d'ancrage](/fr/sessions-api/create-session#placer-les-champs-par-texte-d’ancrage).",
        "required": [
          "text"
        ],
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Texte recherché dans le document. Pour un fichier Word, dans le PDF converti."
          },
          "occurrence": {
            "type": "string",
            "enum": [
              "first",
              "all"
            ],
            "default": "first",
            "description": "`all` place un champ par correspondance ; les clés suivant la première reçoivent `_2`, `_3` et ainsi de suite."
          },
          "offset_x": {
            "type": "number",
            "description": "Ajouté au bord gauche du texte, sous forme de fraction de la largeur de la page."
          },
          "offset_y": {
            "type": "number",
            "description": "Ajouté au bord supérieur du texte, sous forme de fraction de la hauteur de la page."
          },
          "width": {
            "type": "number",
            "minimum": 0.02,
            "maximum": 1,
            "description": "Largeur du champ, exprimée en fraction de la largeur de la page."
          },
          "height": {
            "type": "number",
            "minimum": 0.012,
            "maximum": 1,
            "description": "Hauteur du champ, sous forme de fraction de la hauteur de la page."
          }
        }
      },
      "SignatureFieldResult": {
        "type": "object",
        "description": "Un champ d'un document signé, avec sa valeur sur la copie de ce signataire. Voir [Champs](/fr/core-technology/electronic-signature/report-electronic-signature#champs).",
        "properties": {
          "key": {
            "type": "string",
            "description": "La clé du champ, telle qu'utilisée dans `sign.field_values`."
          },
          "type": {
            "type": "string",
            "enum": [
              "signature",
              "initials",
              "full_name",
              "date_signed",
              "text",
              "checkbox",
              "email",
              "data"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "verified_person",
              "legal_representative",
              "key_people"
            ]
          },
          "label": {
            "type": "string"
          },
          "page": {
            "type": "integer",
            "description": "Numéro de page, à partir de 1. Pour un document Word, page du PDF converti."
          },
          "x": {
            "type": "number",
            "description": "Bord gauche, sous forme de fraction de la largeur de la page."
          },
          "y": {
            "type": "number",
            "description": "Bord supérieur, sous forme de fraction de la hauteur de la page."
          },
          "width": {
            "type": "number",
            "description": "Largeur, exprimée en fraction de la largeur de la page."
          },
          "height": {
            "type": "number",
            "description": "Hauteur, sous forme de fraction de la hauteur de la page."
          },
          "required": {
            "type": "boolean"
          },
          "value": {
            "nullable": true,
            "description": "Une chaîne pour `text`, `email`, `full_name`, `date_signed` et `data`, un booléen pour une `checkbox`, et `true` pour une signature ou des initiales appliquées. `null` si vide."
          },
          "display_value": {
            "type": "string",
            "nullable": true,
            "description": "La valeur telle qu'apposée sur la page : dates dans le `date_format` du champ, `Yes` ou `No` pour une case à cocher, `Signed` pour une signature ou des initiales."
          },
          "value_source": {
            "type": "string",
            "nullable": true,
            "enum": [
              "signer",
              "identity",
              "contact",
              "company",
              "session",
              "metadata",
              "api",
              "signing_time",
              null
            ],
            "description": "Provenance de la valeur : `signer` (saisie, cochée ou appliquée par le signataire), `identity` (la pièce d'identité vérifiée), `contact` (l'e-mail ou le téléphone vérifié), `company` (l'entreprise vérifiée), `session` (`vendor_data`), `metadata`, `api` (`sign.field_values`) ou `signing_time` (la date de signature)."
          },
          "filled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "image_url": {
            "type": "string",
            "nullable": true,
            "description": "Signature et initiales uniquement : chemin de l'image appliquée. Voir [Télécharger une image de signature](/fr/sessions-api/electronic-signature/download-field-image)."
          },
          "value_unavailable_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "source_empty",
              null
            ],
            "description": "`source_empty` lorsqu'un champ prérempli n'avait aucune valeur dans la session et que `signature_field_data_missing_action` a tout de même autorisé le signataire à signer."
          }
        }
      },
      "VaspDirectoryWidgetEntry": {
        "type": "object",
        "description": "Ce que le sélecteur de VASP de l'utilisateur final affiche : l'identité du VASP et s'il peut être contacté.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "L'identifiant de l'entrée, pour GET /v3/travel-rule/vasps/{vasp_id}/."
          },
          "kind": {
            "type": "string",
            "enum": [
              "directory",
              "didit"
            ],
            "description": "directory pour une entrée de l'annuaire partagé ; didit pour un membre du réseau Didit."
          },
          "name": {
            "type": "string"
          },
          "lei": {
            "type": "string"
          },
          "jurisdiction": {
            "type": "string",
            "description": "Code pays ISO 3166, tel que fourni par la source."
          },
          "domains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Les domaines web du VASP. Toujours vide pour les membres du réseau Didit."
          },
          "reachable": {
            "type": "boolean",
            "description": "Indique si votre application dispose d'une route disponible vers ce VASP, ou vers l'une de ses entités pour une marque. Toujours true pour un membre du réseau Didit."
          }
        }
      },
      "TravelRuleDataSharingFields": {
        "type": "object",
        "description": "Les champs que Didit envoie au VASP de contrepartie concernant vos propres utilisateurs, par type d'entité. Le `name` et l'`wallet_address` sont toujours envoyés, quel que soit le contenu de la liste. Un type d'entité que vous n'avez jamais choisi partage tous les champs. Une liste vide est également un choix : elle ne partage que le nom et le portefeuille.",
        "properties": {
          "individual": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "name",
                "wallet_address",
                "address",
                "national_id",
                "customer_identification",
                "date_of_birth",
                "place_of_birth"
              ]
            },
            "description": "Champs partagés concernant une personne physique."
          },
          "company": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "name",
                "wallet_address",
                "address",
                "national_id",
                "customer_identification"
              ]
            },
            "description": "Champs partagés concernant une personne morale."
          }
        }
      },
      "TravelRuleMatchingRules": {
        "type": "object",
        "description": "Niveau de rigueur de la comparaison de chaque champ des données de la contrepartie avec celles dont vous disposez, par type d'entité. Un champ omis conserve sa valeur par défaut. `NONE` ignore la comparaison, `STRICT` requiert exactement les mêmes mots, `CONTAINS` accepte une valeur dont tous les mots apparaissent dans l'autre, `DEFAULT` correspond à la vérification par sous-ensemble standard, et `FUZZY` accepte les graphies proches (et, pour les dates de naissance, l'inversion du jour et du mois).",
        "properties": {
          "individual": {
            "type": "object",
            "description": "Règles pour une personne physique.",
            "properties": {
              "name": {
                "type": "string",
                "enum": [
                  "NONE",
                  "STRICT",
                  "CONTAINS",
                  "DEFAULT",
                  "FUZZY"
                ],
                "description": "Par défaut : suit `name_matching_strictness`."
              },
              "date_of_birth": {
                "type": "string",
                "enum": [
                  "NONE",
                  "STRICT",
                  "CONTAINS",
                  "DEFAULT",
                  "FUZZY"
                ],
                "description": "Valeur par défaut `NONE`."
              },
              "address": {
                "type": "string",
                "enum": [
                  "NONE",
                  "STRICT",
                  "CONTAINS",
                  "DEFAULT",
                  "FUZZY"
                ],
                "description": "Valeur par défaut `NONE`."
              },
              "account": {
                "type": "string",
                "enum": [
                  "NONE",
                  "STRICT",
                  "CONTAINS",
                  "DEFAULT",
                  "FUZZY"
                ],
                "description": "Le portefeuille par lequel l'échange a été acheminé. Par défaut `STRICT`."
              }
            }
          },
          "company": {
            "type": "object",
            "description": "Règles applicables à une personne morale.",
            "properties": {
              "name": {
                "type": "string",
                "enum": [
                  "NONE",
                  "STRICT",
                  "CONTAINS",
                  "DEFAULT",
                  "FUZZY"
                ],
                "description": "Par défaut : suit `name_matching_strictness`."
              },
              "address": {
                "type": "string",
                "enum": [
                  "NONE",
                  "STRICT",
                  "CONTAINS",
                  "DEFAULT",
                  "FUZZY"
                ],
                "description": "Valeur par défaut `NONE`."
              },
              "account": {
                "type": "string",
                "enum": [
                  "NONE",
                  "STRICT",
                  "CONTAINS",
                  "DEFAULT",
                  "FUZZY"
                ],
                "description": "Le portefeuille par lequel l'échange a été acheminé. Par défaut `STRICT`."
              }
            }
          }
        }
      },
      "TravelRuleDataMatch": {
        "type": "object",
        "nullable": true,
        "description": "Comparaison champ par champ des données des parties au transfert avec ce que l'autre partie sait du détenteur du portefeuille. Elle nomme les champs et les résultats, jamais les valeurs, afin de rester lisible pendant que les données de la contrepartie sont masquées. Null jusqu'à ce qu'une comparaison ait été exécutée.",
        "properties": {
          "matched": {
            "type": "boolean",
            "description": "Vrai lorsqu'aucun champ comparé ne diffère."
          },
          "mismatched_fields": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "name",
                "date_of_birth",
                "address",
                "account"
              ]
            },
            "description": "Les champs qui diffèrent."
          },
          "fields": {
            "type": "object",
            "description": "Une entrée par champ comparé pour le type d'entité de la partie (`name`, `date_of_birth`, `address`, `account` ; une entreprise n'a pas de `date_of_birth`).",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "result": {
                  "type": "string",
                  "enum": [
                    "matched",
                    "mismatched",
                    "not_compared"
                  ],
                  "description": "`not_compared` lorsque la règle est `NONE` ou que l'un des deux côtés ne comporte aucune valeur pour le champ."
                },
                "strictness": {
                  "type": "string",
                  "enum": [
                    "NONE",
                    "STRICT",
                    "CONTAINS",
                    "DEFAULT",
                    "FUZZY"
                  ]
                }
              }
            }
          }
        }
      },
      "TravelRuleDataUnmasked": {
        "type": "object",
        "nullable": true,
        "description": "Enregistrement d'audit du moment où les données de la contrepartie ont été démasquées. Null tant que les données sont encore masquées, ainsi que pour les transferts sortants.",
        "properties": {
          "at": {
            "type": "string",
            "format": "date-time"
          },
          "reason": {
            "type": "string",
            "enum": [
              "ownership_confirmed",
              "wallet_proof",
              "address_book_match",
              "own_verified_wallet",
              "inquiry_approved",
              "known_payment_method",
              "travel_address"
            ],
            "description": "Ce qui a confirmé la propriété : ownership_confirmed (votre confirmation via la console ou l'API), wallet_proof (une preuve de portefeuille dans le widget, ou un transfert entrant INTERNAL, défini lors de sa création), address_book_match (un portefeuille vérifié du carnet d'adresses), own_verified_wallet (le portefeuille vérifié propre à votre utilisateur), inquiry_approved (votre approbation d'une demande TRP entrante ou d'un message GTR ou Sygna), known_payment_method (un portefeuille avec lequel votre utilisateur a déjà payé) ou travel_address (la Travel Address par portefeuille qui a nommé le portefeuille)."
          },
          "actor": {
            "type": "string",
            "description": "Qui l'a confirmé : l'e-mail de l'utilisateur de la console ou le libellé de la clé API. Laissé vide pour une décision automatique."
          }
        }
      },
      "TravelRuleMessageAttachment": {
        "type": "object",
        "nullable": true,
        "description": "Le document joint à un message, stocké comme n'importe quel autre document de transaction.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "note": {
            "type": "string",
            "nullable": true
          },
          "uploaded_by": {
            "type": "string",
            "nullable": true,
            "description": "Qui l'a joint. Dans le portail de récupération, un fichier que vous avez envoyé affiche le nom de votre VASP, jamais la personne ou la clé API associée."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "file_url": {
                  "type": "string",
                  "nullable": true,
                  "description": "URL de téléchargement temporaire."
                },
                "original_filename": {
                  "type": "string"
                },
                "file_size": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "TravelRuleMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "MESSAGE",
              "DOCUMENT_REQUEST"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "INBOUND",
              "OUTBOUND"
            ],
            "description": "`OUTBOUND` correspond à ce qui a été envoyé par le côté du lecteur lui-même. Dans le portail de récupération, la direction s'entend du côté de la contrepartie."
          },
          "author": {
            "type": "string",
            "description": "Qui l'a rédigé de son côté : l'e-mail d'un utilisateur de la console, le libellé d'une clé API ou le nom de l'autre VASP."
          },
          "body": {
            "type": "string"
          },
          "requested_documents": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ce qu'une DOCUMENT_REQUEST demande, selon les termes du demandeur."
          },
          "reply_to": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "fulfilled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Défini sur une DOCUMENT_REQUEST dès qu'une réponse à celle-ci comporte un document."
          },
          "attachment": {
            "$ref": "#/components/schemas/TravelRuleMessageAttachment"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TravelRuleMessageCreateRequest": {
        "type": "object",
        "description": "Envoyez au format JSON, ou en multipart/form-data avec les pièces jointes dans `files`.",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "MESSAGE",
              "DOCUMENT_REQUEST"
            ],
            "default": "MESSAGE"
          },
          "body": {
            "type": "string",
            "maxLength": 5000,
            "description": "Requis pour un MESSAGE sauf si un fichier est joint."
          },
          "requested_documents": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 255
            },
            "maxItems": 10,
            "description": "Requis (au moins un) pour un DOCUMENT_REQUEST, et autorisé uniquement dans ce cas."
          },
          "reply_to": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Un message du même transfert. Une réponse contenant un document répond à la demande de document à laquelle elle correspond."
          },
          "files": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "binary"
            },
            "maxItems": 5,
            "description": "Uniquement en multipart. Jusqu'à 5 fichiers de 10 Mo chacun."
          }
        }
      },
      "SessionDeletionJob": {
        "type": "object",
        "description": "Une suppression groupée de sessions en cours en arrière-plan : progression et totaux par résultat, jamais les sessions spécifiques supprimées.",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid",
            "description": "Interrogez `GET /v3/sessions/delete/{job_id}/` avec cet identifiant."
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "COMPLETED",
              "FAILED"
            ],
            "description": "`PENDING` : accepté, pas encore démarré. `PROCESSING` : suppression en cours ; `processed` et `outcomes` sont en cours de mise à jour. `COMPLETED` : chaque session sélectionnée est prise en compte. `FAILED` : la tâche s'est arrêtée prématurément ; voir `error`."
          },
          "total": {
            "type": "integer",
            "description": "Sessions sélectionnées lors de la demande de suppression."
          },
          "processed": {
            "type": "integer",
            "description": "Sessions traitées par la tâche jusqu'à présent."
          },
          "outcomes": {
            "type": "object",
            "description": "Nombre de sessions s'étant terminées par chaque résultat. Chaque clé est toujours présente.",
            "properties": {
              "deleted": {
                "type": "integer",
                "description": "Sessions supprimées avec leur embedding facial."
              },
              "none": {
                "type": "integer",
                "description": "Sessions supprimées qui n'avaient pas d'embedding facial."
              },
              "retained_with_user": {
                "type": "integer",
                "description": "Sessions supprimées alors qu'un gabarit biométrique sans image a été conservé pour leur utilisateur, comme demandé par la requête ou la politique de l'application."
              },
              "ineligible_no_vendor_user": {
                "type": "integer",
                "description": "Sessions supprimées, avec leur embedding facial, car la conservation a été demandée mais aucun utilisateur n'y était lié."
              },
              "failed_retryable": {
                "type": "integer",
                "description": "Sessions signalées comme non supprimées. Une tâche réessaie de supprimer par elle-même un groupe qu'elle n'a pas pu supprimer au lieu de le comptabiliser ici."
              },
              "already_deleted": {
                "type": "integer",
                "description": "Sessions sélectionnées qui étaient déjà supprimées, par exemple par une autre requête, lorsque la tâche les a atteintes."
              }
            }
          },
          "deleted_child_verifications": {
            "type": "integer",
            "description": "Vérifications créées par les vérifications d'entreprise supprimées, supprimées avec elles. Vaut toujours `0` pour une tâche initiée par `POST /v3/sessions/delete/`, qui supprime uniquement les sessions KYC."
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "`null` sauf si `status` est `FAILED` ; indique alors la raison de l'interruption de la suppression. Les sessions que la tâche n'avait pas encore atteintes sont conservées : répétez la requête pour les supprimer."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles la suppression a été demandée."
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où la tâche s'est terminée ; `null` pendant son exécution."
          }
        }
      },
      "EntityStatusUpdateRequest": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "FLAGGED",
              "BLOCKED"
            ],
            "description": "Nouveau statut de cycle de vie. `BLOCKED` ajoute également le `vendor_data` à la liste de blocage du système."
          }
        }
      },
      "AMLMonitoringToggleResult": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "users_total",
              "already_enabled",
              "with_existing_aml",
              "needing_screening",
              "skipped_no_identity_data",
              "skipped_blocked",
              "estimated_screening_cost_usd",
              "estimated_annual_monitoring_cost_usd",
              "balance_sufficient",
              "unmatched"
            ],
            "description": "Aperçu du coût. Renvoyé directement lorsque estimate_only est vrai (rien n'est écrit).",
            "properties": {
              "users_total": {
                "type": "integer",
                "description": "Profils correspondant à la sélection."
              },
              "already_enabled": {
                "type": "integer",
                "description": "Profils déjà surveillés (aucune action lors de l'activation ; ce sont ceux que la désactivation désactive)."
              },
              "with_existing_aml": {
                "type": "integer",
                "description": "Profils dont le filtrage AML existant passera en mode surveillé (aucun nouveau filtrage)."
              },
              "needing_screening": {
                "type": "integer",
                "description": "Profils sans aucun filtrage AML qui seront d'abord filtrés (facturés comme un filtrage AML standard)."
              },
              "skipped_no_identity_data": {
                "type": "integer",
                "description": "Profils ne pouvant pas faire l'objet d'un filtrage en raison de données d'identité manquantes."
              },
              "skipped_blocked": {
                "type": "integer",
                "description": "Utilisateurs bloqués qui seront ignorés (toujours 0 pour les entreprises)."
              },
              "estimated_screening_cost_usd": {
                "type": "number",
                "example": 0.2,
                "description": "Coût ponctuel des nouveaux filtrages."
              },
              "estimated_annual_monitoring_cost_usd": {
                "type": "number",
                "example": 0.07,
                "description": "Coût de surveillance annuel des profils qui deviendront surveillés."
              },
              "balance_sufficient": {
                "type": "boolean",
                "description": "Indique si le solde de l'organisation couvre le filtrage ainsi que la première année de surveillance."
              },
              "unmatched": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Identifiants de la requête ne correspondant à aucun profil dans cette application, exactement tels qu'envoyés."
              }
            }
          },
          {
            "type": "object",
            "required": [
              "job_id",
              "status",
              "is_enabled",
              "target_type",
              "total",
              "processed",
              "outcomes",
              "results",
              "error",
              "created_at",
              "completed_at",
              "estimate",
              "unmatched"
            ],
            "properties": {
              "job_id": {
                "type": "string",
                "format": "uuid"
              },
              "status": {
                "type": "string",
                "enum": [
                  "PENDING",
                  "PROCESSING",
                  "COMPLETED",
                  "FAILED"
                ]
              },
              "is_enabled": {
                "type": "boolean",
                "description": "true lorsque le traitement active la surveillance, false lorsqu'il la désactive."
              },
              "target_type": {
                "type": "string",
                "enum": [
                  "user",
                  "business"
                ],
                "description": "Quelle famille de profils la tâche active ou désactive."
              },
              "total": {
                "type": "integer",
                "description": "Profils traités par la tâche."
              },
              "processed": {
                "type": "integer",
                "description": "Profils traités jusqu'à présent."
              },
              "outcomes": {
                "type": "object",
                "description": "Compteurs de résultats par enregistrement. Chaque profil sélectionné est associé à exactement un compteur ; rien n'est ignoré silencieusement.",
                "properties": {
                  "enabled": {
                    "type": "integer",
                    "description": "Surveillance activée sur un filtrage AML existant."
                  },
                  "screened_and_enabled": {
                    "type": "integer",
                    "description": "Un nouveau filtrage AML a été créé (facturé) et la surveillance y a été activée."
                  },
                  "already_enabled": {
                    "type": "integer",
                    "description": "La surveillance était déjà active ; rien n'a changé et rien n'a été facturé."
                  },
                  "disabled": {
                    "type": "integer",
                    "description": "Surveillance désactivée sur l'ensemble des filtrages AML du profil."
                  },
                  "skipped_no_identity_data": {
                    "type": "integer",
                    "description": "Ignoré : le profil ne contient pas le nom complet, la date de naissance et le pays (utilisateurs) ou un nom (entreprises) nécessaires pour le filtrage."
                  },
                  "skipped_blocked": {
                    "type": "integer",
                    "description": "Ignoré : l'utilisateur est bloqué."
                  },
                  "skipped_sandbox": {
                    "type": "integer",
                    "description": "Ignoré : application en sandbox, aucun filtrage n'est créé."
                  },
                  "failed_provider": {
                    "type": "integer",
                    "description": "Le filtrage n'a pas pu être effectué ; réessayez plus tard."
                  },
                  "failed_insufficient_balance": {
                    "type": "integer",
                    "description": "Le solde a été épuisé pendant l'exécution de la tâche."
                  }
                }
              },
              "results": {
                "type": "array",
                "description": "Une entrée par profil traité, dans l'ordre de traitement. S'allonge pendant l'exécution de la tâche ; complet une fois que le statut est COMPLETED. Enregistré pour les tâches démarrées via l'API.",
                "items": {
                  "type": "object",
                  "properties": {
                    "didit_internal_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifiant interne Didit du profil."
                    },
                    "vendor_data": {
                      "type": "string",
                      "nullable": true,
                      "description": "Votre propre identifiant pour le profil."
                    },
                    "outcome": {
                      "type": "string",
                      "enum": [
                        "enabled",
                        "screened_and_enabled",
                        "already_enabled",
                        "disabled",
                        "skipped_no_identity_data",
                        "skipped_blocked",
                        "skipped_sandbox",
                        "failed_provider",
                        "failed_insufficient_balance"
                      ]
                    }
                  }
                }
              },
              "error": {
                "type": "string",
                "nullable": true,
                "description": "Message d'échec générique lorsque le statut est FAILED ; la cause détaillée est conservée côté plateforme."
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "completed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "estimate": {
                "type": "object",
                "description": "Aperçu du coût. Renvoyé directement lorsque estimate_only est vrai (rien n'est écrit).",
                "properties": {
                  "users_total": {
                    "type": "integer",
                    "description": "Profils correspondant à la sélection."
                  },
                  "already_enabled": {
                    "type": "integer",
                    "description": "Profils déjà surveillés (aucune action lors de l'activation ; ce sont ceux que la désactivation désactive)."
                  },
                  "with_existing_aml": {
                    "type": "integer",
                    "description": "Profils dont le filtrage AML existant passera en mode surveillé (aucun nouveau filtrage)."
                  },
                  "needing_screening": {
                    "type": "integer",
                    "description": "Profils sans aucun filtrage AML qui seront d'abord filtrés (facturés comme un filtrage AML standard)."
                  },
                  "skipped_no_identity_data": {
                    "type": "integer",
                    "description": "Profils ne pouvant pas faire l'objet d'un filtrage en raison de données d'identité manquantes."
                  },
                  "skipped_blocked": {
                    "type": "integer",
                    "description": "Utilisateurs bloqués qui seront ignorés (toujours 0 pour les entreprises)."
                  },
                  "estimated_screening_cost_usd": {
                    "type": "number",
                    "example": 0.2,
                    "description": "Coût ponctuel des nouveaux filtrages."
                  },
                  "estimated_annual_monitoring_cost_usd": {
                    "type": "number",
                    "example": 0.07,
                    "description": "Coût de surveillance annuel des profils qui deviendront surveillés."
                  },
                  "balance_sufficient": {
                    "type": "boolean",
                    "description": "Indique si le solde de l'organisation couvre le filtrage ainsi que la première année de surveillance."
                  }
                }
              },
              "unmatched": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Identifiants de la requête ne correspondant à aucun profil dans cette application, exactement tels qu'envoyés. Ils ne font pas partie de la tâche."
              }
            }
          }
        ]
      },
      "AMLMonitoringJob": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "COMPLETED",
              "FAILED"
            ]
          },
          "is_enabled": {
            "type": "boolean",
            "description": "true lorsque le traitement active la surveillance, false lorsqu'il la désactive."
          },
          "target_type": {
            "type": "string",
            "enum": [
              "user",
              "business"
            ],
            "description": "Quelle famille de profils la tâche active ou désactive."
          },
          "total": {
            "type": "integer",
            "description": "Profils traités par la tâche."
          },
          "processed": {
            "type": "integer",
            "description": "Profils traités jusqu'à présent."
          },
          "outcomes": {
            "type": "object",
            "description": "Compteurs de résultats par enregistrement. Chaque profil sélectionné est associé à exactement un compteur ; rien n'est ignoré silencieusement.",
            "properties": {
              "enabled": {
                "type": "integer",
                "description": "Surveillance activée sur un filtrage AML existant."
              },
              "screened_and_enabled": {
                "type": "integer",
                "description": "Un nouveau filtrage AML a été créé (facturé) et la surveillance y a été activée."
              },
              "already_enabled": {
                "type": "integer",
                "description": "La surveillance était déjà active ; rien n'a changé et rien n'a été facturé."
              },
              "disabled": {
                "type": "integer",
                "description": "Surveillance désactivée sur l'ensemble des filtrages AML du profil."
              },
              "skipped_no_identity_data": {
                "type": "integer",
                "description": "Ignoré : le profil ne contient pas le nom complet, la date de naissance et le pays (utilisateurs) ou un nom (entreprises) nécessaires pour le filtrage."
              },
              "skipped_blocked": {
                "type": "integer",
                "description": "Ignoré : l'utilisateur est bloqué."
              },
              "skipped_sandbox": {
                "type": "integer",
                "description": "Ignoré : application en sandbox, aucun filtrage n'est créé."
              },
              "failed_provider": {
                "type": "integer",
                "description": "Le filtrage n'a pas pu être effectué ; réessayez plus tard."
              },
              "failed_insufficient_balance": {
                "type": "integer",
                "description": "Le solde a été épuisé pendant l'exécution de la tâche."
              }
            }
          },
          "results": {
            "type": "array",
            "description": "Une entrée par profil traité, dans l'ordre de traitement. S'allonge pendant l'exécution de la tâche ; complet une fois que le statut est COMPLETED. Enregistré pour les tâches démarrées via l'API.",
            "items": {
              "type": "object",
              "properties": {
                "didit_internal_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Identifiant interne Didit du profil."
                },
                "vendor_data": {
                  "type": "string",
                  "nullable": true,
                  "description": "Votre propre identifiant pour le profil."
                },
                "outcome": {
                  "type": "string",
                  "enum": [
                    "enabled",
                    "screened_and_enabled",
                    "already_enabled",
                    "disabled",
                    "skipped_no_identity_data",
                    "skipped_blocked",
                    "skipped_sandbox",
                    "failed_provider",
                    "failed_insufficient_balance"
                  ]
                }
              }
            }
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Message d'échec générique lorsque le statut est FAILED ; la cause détaillée est conservée côté plateforme."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "estimate": {
            "type": "object",
            "description": "Aperçu du coût. Renvoyé directement lorsque estimate_only est vrai (rien n'est écrit).",
            "properties": {
              "users_total": {
                "type": "integer",
                "description": "Profils correspondant à la sélection."
              },
              "already_enabled": {
                "type": "integer",
                "description": "Profils déjà surveillés (aucune action lors de l'activation ; ce sont ceux que la désactivation désactive)."
              },
              "with_existing_aml": {
                "type": "integer",
                "description": "Profils dont le filtrage AML existant passera en mode surveillé (aucun nouveau filtrage)."
              },
              "needing_screening": {
                "type": "integer",
                "description": "Profils sans aucun filtrage AML qui seront d'abord filtrés (facturés comme un filtrage AML standard)."
              },
              "skipped_no_identity_data": {
                "type": "integer",
                "description": "Profils ne pouvant pas faire l'objet d'un filtrage en raison de données d'identité manquantes."
              },
              "skipped_blocked": {
                "type": "integer",
                "description": "Utilisateurs bloqués qui seront ignorés (toujours 0 pour les entreprises)."
              },
              "estimated_screening_cost_usd": {
                "type": "number",
                "example": 0.2,
                "description": "Coût ponctuel des nouveaux filtrages."
              },
              "estimated_annual_monitoring_cost_usd": {
                "type": "number",
                "example": 0.07,
                "description": "Coût de surveillance annuel des profils qui deviendront surveillés."
              },
              "balance_sufficient": {
                "type": "boolean",
                "description": "Indique si le solde de l'organisation couvre le filtrage ainsi que la première année de surveillance."
              }
            }
          },
          "unmatched": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Identifiants de la requête ne correspondant à aucun profil dans cette application, exactement tels qu'envoyés. Ils ne font pas partie de la tâche."
          }
        }
      },
      "OngoingMonitoringToggleRequest": {
        "type": "object",
        "required": [
          "is_enabled"
        ],
        "properties": {
          "is_enabled": {
            "type": "boolean",
            "description": "true pour activer la surveillance, false pour la désactiver."
          },
          "estimate_only": {
            "type": "boolean",
            "default": false,
            "description": "Si true, renvoie l'estimation des coûts et n'effectue aucune écriture."
          },
          "update_all": {
            "type": "boolean",
            "default": false,
            "description": "S'applique à chaque entité de l'application (restreint par les paramètres filter_* lorsqu'ils sont présents)."
          },
          "filter_search": {
            "type": "string"
          },
          "filter_status": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "filter_country": {
            "type": "string"
          },
          "filter_date_from": {
            "type": "string",
            "format": "date"
          },
          "filter_date_to": {
            "type": "string",
            "format": "date"
          },
          "didit_internal_id_list": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Entités à basculer. Requis sauf si update_all est true."
          }
        }
      },
      "OngoingMonitoringJob": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "COMPLETED",
              "FAILED"
            ]
          },
          "is_enabled": {
            "type": "boolean"
          },
          "total": {
            "type": "integer"
          },
          "processed": {
            "type": "integer"
          },
          "outcomes": {
            "type": "object",
            "description": "Compteurs de résultats par entité. Rien n'est ignoré silencieusement : chaque entité demandée est résolue en exactement un compteur.",
            "properties": {
              "enabled": {
                "type": "integer",
                "description": "Surveillance activée sur un filtrage AML existant."
              },
              "screened_and_enabled": {
                "type": "integer",
                "description": "Un nouveau filtrage AML a été créé (facturé) et la surveillance activée."
              },
              "already_enabled": {
                "type": "integer",
                "description": "La surveillance était déjà active (les lignes en double héritées sont consolidées)."
              },
              "disabled": {
                "type": "integer",
                "description": "Surveillance désactivée sur chaque ligne AML de l'entité."
              },
              "skipped_no_identity_data": {
                "type": "integer",
                "description": "Ignoré : aucun nom complet + date de naissance + pays disponible pour le filtrage."
              },
              "skipped_blocked": {
                "type": "integer",
                "description": "Ignoré : l'utilisateur est bloqué."
              },
              "skipped_sandbox": {
                "type": "integer",
                "description": "Ignoré : application en sandbox."
              },
              "failed_provider": {
                "type": "integer",
                "description": "L'appel au fournisseur de filtrage a échoué."
              },
              "failed_insufficient_balance": {
                "type": "integer",
                "description": "Solde épuisé en cours de tâche."
              }
            }
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "estimate": {
            "type": "object",
            "description": "Aperçu du coût. Renvoyé directement lorsque estimate_only est vrai (aucune écriture n'est effectuée).",
            "properties": {
              "users_total": {
                "type": "integer",
                "description": "Entités dans la sélection."
              },
              "already_enabled": {
                "type": "integer"
              },
              "with_existing_aml": {
                "type": "integer",
                "description": "Entités dont le filtrage AML existant passera en mode surveillé."
              },
              "needing_screening": {
                "type": "integer",
                "description": "Entités sans aucun filtrage AML qui seront filtrées en premier (facturées)."
              },
              "skipped_no_identity_data": {
                "type": "integer"
              },
              "skipped_blocked": {
                "type": "integer"
              },
              "estimated_screening_cost_usd": {
                "type": "number",
                "example": 0.2
              },
              "estimated_annual_monitoring_cost_usd": {
                "type": "number",
                "example": 0.07
              },
              "balance_sufficient": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "OngoingMonitoringToggleResult": {
        "oneOf": [
          {
            "type": "object",
            "description": "Aperçu du coût. Renvoyé directement lorsque estimate_only est vrai (aucune écriture n'est effectuée).",
            "properties": {
              "users_total": {
                "type": "integer",
                "description": "Entités dans la sélection."
              },
              "already_enabled": {
                "type": "integer"
              },
              "with_existing_aml": {
                "type": "integer",
                "description": "Entités dont le filtrage AML existant passera en mode surveillé."
              },
              "needing_screening": {
                "type": "integer",
                "description": "Entités sans aucun filtrage AML qui seront filtrées en premier (facturées)."
              },
              "skipped_no_identity_data": {
                "type": "integer"
              },
              "skipped_blocked": {
                "type": "integer"
              },
              "estimated_screening_cost_usd": {
                "type": "number",
                "example": 0.2
              },
              "estimated_annual_monitoring_cost_usd": {
                "type": "number",
                "example": 0.07
              },
              "balance_sufficient": {
                "type": "boolean"
              }
            }
          },
          {
            "$ref": "#/components/schemas/OngoingMonitoringJob"
          }
        ]
      },
      "CaseBlueprintPresetInstallResult": {
        "type": "object",
        "properties": {
          "created": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CaseBulkUpdateResult": {
        "type": "object",
        "properties": {
          "updated": {
            "type": "integer"
          },
          "failures": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "case_uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "detail": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "RegulatoryReportList": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Nombre de lignes correspondantes, plafonné à 100 pour des raisons de performance."
          },
          "next": {
            "type": "string",
            "nullable": true
          },
          "previous": {
            "type": "string",
            "nullable": true
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RegulatoryReportDetail"
            }
          }
        }
      },
      "EntityNetworkMembershipList": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EntityNetworkMembership"
            }
          }
        }
      },
      "SessionDecision": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "L'identifiant unique de la session."
          },
          "session_kind": {
            "type": "string",
            "enum": [
              "user",
              "business"
            ],
            "description": "Discriminateur indiquant s'il s'agit d'une session de Vérification des utilisateurs (KYC) ou de Vérification d'entreprise (KYB). Lorsque la valeur est `user`, les tableaux de fonctionnalités KYC (`id_verifications`, `nfc_verifications`, `liveness_checks`, `face_matches`, `poa_verifications`, `document_ai_documents`, `database_validations`, ...) s'appliquent et les tableaux d'entreprise sont absents. Lorsque la valeur est `business`, le payload contient à la place `registry_checks`, `document_verifications`, `key_people_checks` ainsi que les tableaux partagés (`aml_screenings`, `phone_verifications`, `email_verifications`, `ip_analyses`, `questionnaire_responses`). **Omis lorsque `include=events` est transmis** — le format des événements n'existe que pour les sessions utilisateur, le discriminateur est donc supprimé de cette variante."
          },
          "shared_from_session": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Pour une session clonée avec `POST /v3/session/import-shared/` : le `session_id` de la session d'origine dans l'application source. `null` pour toute autre session. Omis lorsque `include=events` est transmis."
          },
          "shared_from_session_number": {
            "type": "integer",
            "nullable": true,
            "description": "`session_number` de la session source lorsque cette session a été importée depuis une autre application de votre organisation. `null` sinon."
          },
          "session_number": {
            "type": "integer",
            "description": "Le numéro de la session.",
            "nullable": true
          },
          "session_url": {
            "type": "string",
            "format": "uri",
            "description": "L'URL de la session.",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "Not Started",
              "In Progress",
              "Awaiting User",
              "In Review",
              "Approved",
              "Declined",
              "Resubmitted",
              "Expired",
              "Kyc Expired",
              "Abandoned"
            ],
            "description": "Statut global du cycle de vie de la session — le résultat consolidé du workflow. Les valeurs finales sont `Approved`, `Declined`, `In Review`, `Expired`, `Kyc Expired` et `Abandoned` ; `Not Started`, `In Progress`, `Awaiting User` et `Resubmitted` indiquent que la session progresse toujours dans le workflow."
          },
          "status_override": {
            "type": "object",
            "nullable": true,
            "description": "Présent lorsqu'un réviseur a défini manuellement `status`. `null` lorsque le statut est le résultat automatique. Utilisez-le pour distinguer une approbation manuelle d'une approbation automatique.",
            "properties": {
              "overridden_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "automatic_status": {
                "type": "string",
                "nullable": true,
                "description": "Le statut conclu par les propres vérifications de la plateforme."
              }
            }
          },
          "decision_trace": {
            "type": "object",
            "description": "Manière dont le statut a été atteint : qui l'a défini et quels avertissements l'ont provoqué.",
            "properties": {
              "status": {
                "type": "string",
                "description": "Le statut de la session."
              },
              "decided_by": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "manual",
                  "automatic",
                  "investigator",
                  null
                ],
                "description": "Qui a défini le statut. `null` tant que la session n'est pas décidée."
              },
              "decided_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "automatic_status": {
                "type": "string",
                "nullable": true,
                "description": "Ce que concluent les propres vérifications de la plateforme, ce qui diffère de `status` après une décision manuelle."
              },
              "terminal_node_id": {
                "type": "string",
                "nullable": true,
                "description": "Le nœud d'état du workflow qui a mis fin à la session, le cas échéant."
              },
              "actor": {
                "type": "object",
                "nullable": true,
                "description": "Le réviseur à l'origine d'une décision manuelle.",
                "properties": {
                  "user": {
                    "type": "string",
                    "nullable": true
                  },
                  "actor_type": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "warning_counts": {
                "type": "object",
                "description": "Avertissements par `log_type` (`error`, `warning`, `information`) et `total`.",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "status_warnings": {
                "type": "array",
                "description": "Les avertissements qui définissent un statut `Declined` ou `In Review`.",
                "items": {
                  "type": "object",
                  "properties": {
                    "risk": {
                      "type": "string"
                    },
                    "feature": {
                      "type": "string",
                      "nullable": true
                    },
                    "node_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "log_type": {
                      "type": "string",
                      "nullable": true
                    },
                    "check_status": {
                      "type": "string",
                      "nullable": true
                    },
                    "source": {
                      "type": "string",
                      "description": "La liste du payload d'où provient l'avertissement, par exemple `id_verifications`."
                    },
                    "short_description": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "linked_records": {
            "type": "object",
            "nullable": true,
            "description": "Un résumé des autres enregistrements liés à la session. `null` lorsqu'il n'y a rien à afficher, ainsi que pour les workflows déclarant une norme d'assurance de l'âge.",
            "properties": {
              "same_face": {
                "type": "object",
                "nullable": true,
                "description": "Autres personnes dont le visage correspondait à l'une des recherches faciales de cette session.",
                "properties": {
                  "count": {
                    "type": "integer"
                  },
                  "best_match": {
                    "type": "object",
                    "nullable": true,
                    "properties": {
                      "session_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                      },
                      "session_number": {
                        "type": "integer",
                        "nullable": true
                      },
                      "vendor_user_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                      },
                      "similarity_percentage": {
                        "type": "number",
                        "nullable": true
                      }
                    }
                  }
                }
              },
              "earlier_verifications": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "count": {
                    "type": "integer"
                  },
                  "vendor_user_id": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  }
                }
              },
              "networks": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "count": {
                    "type": "integer"
                  },
                  "open": {
                    "type": "integer"
                  },
                  "dismissed": {
                    "type": "integer"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "network_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "display_number": {
                          "type": "integer",
                          "nullable": true
                        },
                        "name": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "risk_score": {
                          "type": "number",
                          "nullable": true
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant stable du groupe de workflows qui a généré cette session. Les workflows sont versionnés — cette valeur identifie le workflow lui-même, et non la version spécifique.",
            "nullable": true
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "La fonctionnalité de la session."
            },
            "description": "Liste des fonctionnalités de vérification configurées pour cette session, sous forme de noms d'affichage : `ID_VERIFICATION`, `NFC`, `LIVENESS`, `FACE_MATCH`, `POA`, `PHONE`, `EMAIL_VERIFICATION`, `AML`, `IP_ANALYSIS`, `DATABASE_VALIDATION`, `QUESTIONNAIRE`, `AGE_ESTIMATION`, `FACE_SEARCH`, `GEOLOCATION` (vérification de la localisation) (les sessions de Vérification d'entreprise (KYB) utilisent l'ensemble de fonctionnalités KYB : `KYB_REGISTRY`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE`, `AML`, `PHONE`, `EMAIL_VERIFICATION`, `IP_ANALYSIS`, `QUESTIONNAIRE`). Avec `include=events`, chaque entrée devient un objet `{feature, node_id}` au lieu d'une simple chaîne, et la fonctionnalité d'e-mail est renommée : elle apparaît sous la forme `EMAIL` en mode événements au lieu de `EMAIL_VERIFICATION` utilisé ici."
          },
          "vendor_data": {
            "type": "string",
            "description": "Les données du fournisseur (vendor data) de la session.",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "description": "Les métadonnées de la session.",
            "nullable": true
          },
          "expected_details": {
            "type": "object",
            "description": "Informations attendues fournies lors de la création de la session — utilisées pour la validation croisée avec les données extraites (KYC) ou pour préremplir la recherche dans le registre des sociétés (KYB). Renvoie exactement les clés fournies ; `null` si aucune n'a été fournie. Les sessions KYC contiennent les champs relatifs à la personne ; les sessions de Vérification d'entreprise (KYB) contiennent `company_name`, `registry_country` et `registration_number`.",
            "properties": {
              "first_name": {
                "type": "string",
                "description": "Prénom de l'utilisateur. Par exemple, `John`."
              },
              "last_name": {
                "type": "string",
                "description": "Nom de famille de l'utilisateur. Par exemple, `Doe`."
              },
              "date_of_birth": {
                "type": "string",
                "format": "date",
                "description": "Date de naissance de l'utilisateur au format : YYYY-MM-DD. Par exemple, `1990-05-15`."
              },
              "gender": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "M",
                  "F"
                ],
                "default": null,
                "description": "Genre de l'utilisateur. Doit être 'M', 'F' ou null."
              },
              "nationality": {
                "type": "string",
                "description": "Code pays ISO 3166-1 alpha-3 représentant le pays d'origine du candidat. Par exemple, `USA`."
              },
              "country": {
                "type": "string",
                "description": "Code pays ISO 3166-1 alpha-3 représentant le pays du document de Justificatif de domicile, ou le pays du document d'identité du candidat, qui peut différer de la nationalité. Par exemple, `GBR`."
              },
              "address": {
                "type": "string",
                "description": "L'adresse dans un format lisible par un humain, comprenant autant d'informations que possible. Par exemple, `123 Main St, San Francisco, CA 94105, USA`."
              },
              "identification_number": {
                "type": "string",
                "description": "Le numéro de document, le numéro personnel ou l'identifiant fiscal de l'utilisateur. Par exemple, `123456789`."
              },
              "ip_address": {
                "type": "string",
                "format": "ipv4",
                "description": "Adresse IP attendue pour la session. Si l'adresse IP réelle diffère de cette valeur, un avertissement sera consigné. Par exemple, `192.168.1.100`."
              },
              "expected_document_types": {
                "type": "array",
                "description": "Types de documents auxquels l'étape de vérification d'identité a été restreinte lors de la création de la session. Vide/non défini signifie aucune restriction. Codes : `P` (passeport), `ID` (carte nationale d'identité), `DL` (permis de conduire), `RP` (titre de séjour), `HIC` (carte d'assurance maladie), `TC` (carte fiscale), `SSC` (carte de sécurité sociale).",
                "items": {
                  "type": "string",
                  "enum": [
                    "P",
                    "ID",
                    "DL",
                    "RP",
                    "HIC",
                    "TC",
                    "SSC"
                  ]
                }
              },
              "id_country": {
                "type": "string",
                "nullable": true,
                "description": "Pays de délivrance attendu de la pièce d'identité (ISO 3166-1 alpha-3), lorsqu'il est restreint au moment de la création.",
                "example": "ESP"
              },
              "poa_country": {
                "type": "string",
                "nullable": true,
                "description": "Pays attendu du justificatif de domicile (ISO 3166-1 alpha-3), lorsqu'il est restreint au moment de la création.",
                "example": "ESP"
              },
              "company_name": {
                "type": "string",
                "description": "Raison sociale attendue de l'entreprise. Sessions de Vérification d'entreprise (KYB) uniquement."
              },
              "registry_country": {
                "type": "string",
                "description": "Pays du registre attendu au format `XX` ou `XX-YY` (ISO 3166-1 alpha-2, éventuellement avec une subdivision ISO 3166-2 pour les registres au niveau de l'État, par ex. `US-CA`). Sessions de vérification d'entreprise (KYB) uniquement."
              },
              "registration_number": {
                "type": "string",
                "description": "Numéro d'immatriculation de l'entreprise attendu. Sessions d'entreprise (KYB) uniquement."
              }
            },
            "nullable": true
          },
          "contact_details": {
            "type": "object",
            "description": "Coordonnées fournies lors de la création de la session (utilisées pour les e-mails de notification, la vérification préremplie du téléphone/de l'e-mail et la langue de communication). `null` si aucun e-mail ni numéro de téléphone n'a été fourni.",
            "properties": {
              "email": {
                "type": "string",
                "description": "Adresse e-mail de l'utilisateur (par exemple, « john.doe@example.com ») qui sera utilisée lors de l'étape de Vérification de l'e-mail. Si elle n'est pas fournie, l'utilisateur doit la renseigner pendant le flux de vérification."
              },
              "email_lang": {
                "type": "string",
                "description": "Code de langue (ISO 639-1) pour les notifications par e-mail. Contrôle la langue de toutes les communications par e-mail (par exemple, \"en\", \"es\", \"fr\")."
              },
              "send_notification_emails": {
                "type": "boolean",
                "default": false,
                "description": "Si la valeur est true et qu'un e-mail est fourni, Didit envoie l'e-mail initial « Vérifiez votre identité » de manière asynchrone lors de la création de la session de vérification des utilisateurs (KYC) ou de vérification d'entreprise (KYB). Didit envoie également les notifications de statut de vérification pour les sessions nécessitant un examen manuel à l'adresse e-mail fournie."
              },
              "phone": {
                "type": "string",
                "nullable": true,
                "description": "Numéro de téléphone de l'utilisateur au format E.164 s'il est disponible (par ex. +14155552671). `null` si seul un e-mail a été fourni lors de la création de la session. Remarque : ce champ renvoie le numéro de téléphone d'origine fourni lors de la création de la session. Si le numéro était invalide, il se peut qu'il ne soit pas au format E.164."
              }
            },
            "nullable": true
          },
          "callback": {
            "type": "string",
            "format": "uri",
            "description": "L'URL de rappel de la session.",
            "nullable": true
          },
          "id_verifications": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de Vérification d'identité (OCR)** produits par les étapes de document d'identité dans le graphe du workflow. Toujours un tableau JSON — lisez `id_verifications[0]` et itérez si votre workflow peut exécuter plusieurs vérifications d'identité (par exemple une vérification principale plus un contrôle renforcé). `null` jusqu'à ce qu'au moins une étape d'identité ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, le `status` au niveau de la fonctionnalité, les champs de document extraits, les URL des images, les scores de qualité, la MRZ, l'analyse d'adresse, les correspondances entre sessions et `warnings[]`.",
            "items": {
              "type": "object",
              "description": "Un rapport de vérification d'identité - le rapport complet pour une seule étape de Vérification d'identité. `verification_method` indique laquelle des trois méthodes l'a produit (capture de document, recherche sans document ou connexion par portefeuille) et le bloc de preuves spécifique à la méthode est renseigné en conséquence.",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "ID de nœud du graphe de workflow de l'étape OCR ayant produit ce rapport."
                },
                "verification_method": {
                  "type": "string",
                  "enum": [
                    "document",
                    "id_lookup",
                    "wallet"
                  ],
                  "description": "Quelle méthode de Vérification d'identité a généré ce rapport. `document` - l'utilisateur a photographié une pièce d'identité physique (valeur par défaut, et valeur de chaque session créée avant l'existence des autres méthodes). `id_lookup` - l'utilisateur a saisi son numéro d'identité national, qui a été vérifié auprès d'un registre gouvernemental ou d'une autre source faisant autorité pour ce pays (`id_lookup.source` en indique le nom). `wallet` - l'utilisateur s'est connecté à l'aide d'une identité numérique gouvernementale ou bancaire."
                },
                "assurance": {
                  "type": "string",
                  "enum": [
                    "documentary",
                    "data_match",
                    "cryptographic"
                  ],
                  "description": "Niveau d'assurance dérivé de `verification_method` : `documentary` pour un document qui a été capturé et vérifié, `data_match` pour des informations qui correspondaient à un enregistrement détenu par la source interrogée, `cryptographic` pour des attributs qu'un fournisseur d'identité a authentifiés et signés."
                },
                "wallet_provider": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identifiant de portefeuille du catalogue lorsque `verification_method` est `wallet` (`mitid`, `bankid_se`, `itsme`, ...). `null` sinon."
                },
                "fallback_from": {
                  "type": "object",
                  "nullable": true,
                  "description": "Raison pour laquelle une méthode sans document n'a pas finalisé l'étape d'identité. Défini lorsqu'une recherche ou une connexion par portefeuille a échoué : sur la vérification de document que l'utilisateur a poursuivie lorsque le mécanisme de repli du pays était `fallback_to_document` (`action` est `fallback_to_document`), ou sur le rapport refusé lorsqu'il s'agissait de `decline`. `null` dans le cas contraire.",
                  "properties": {
                    "method": {
                      "type": "string",
                      "enum": [
                        "id_lookup",
                        "wallet"
                      ],
                      "description": "La méthode ayant échoué."
                    },
                    "reason": {
                      "type": "string",
                      "description": "L'issue qui y a mis fin, par ex. `no_match`, `provider_error`, `cancelled`, `timeout`."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "fallback_to_document",
                        "decline"
                      ],
                      "description": "L'action configurée qui a été effectuée : `fallback_to_document` ou `decline`."
                    }
                  }
                },
                "id_lookup": {
                  "type": "object",
                  "nullable": true,
                  "description": "Preuve du registre. Présente uniquement lorsque `verification_method` est `id_lookup` ; `null` dans le cas contraire.",
                  "properties": {
                    "source": {
                      "type": "string",
                      "description": "Nom côté client de la source interrogée, par ex. `Department of Home Affairs` (un registre gouvernemental) ou `UK credit bureau and financial services records` (pas un registre gouvernemental). Il s'agit de la seule indication de la provenance de la recherche ; ne supposez pas qu'il s'agisse d'une source gouvernementale."
                    },
                    "checked_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Moment où le registre a répondu."
                    },
                    "attempts": {
                      "type": "integer",
                      "description": "Numéro de tentative (à partir de 1) dont provient ce rapport."
                    },
                    "max_attempts": {
                      "type": "integer",
                      "description": "Budget de tentatives configuré pour le pays (1 à 5, valeur par défaut : 1)."
                    },
                    "outcome": {
                      "type": "string",
                      "enum": [
                        "match",
                        "partial_match",
                        "no_match",
                        "provider_error",
                        "format_rejected"
                      ],
                      "nullable": true,
                      "description": "Ce que le registre a répondu. Seuls `match`, `partial_match` et `no_match` sont décomptés du budget de tentatives et facturés."
                    },
                    "comparison": {
                      "type": "array",
                      "description": "Une ligne par champ comparable pour lequel la source a fourni une réponse, plus une ligne par erreur de source. Les lignes de comparaison utilisent les noms de champs normalisés ci-dessous plutôt que les clés de champs de requête spécifiques au pays, car plusieurs champs de requête (prénom et nom, ou n'importe quel alias d'identifiant) sont regroupés en une seule comparaison. Une source ayant échoué ajoute une ligne avec `field: \"provider\"` et `result: \"error\"` ; lisez donc `result` avant de considérer une ligne comme le verdict d'un champ.",
                      "items": {
                        "type": "object",
                        "required": [
                          "field",
                          "label",
                          "provided",
                          "record",
                          "result"
                        ],
                        "properties": {
                          "field": {
                            "type": "string",
                            "enum": [
                              "identification_number",
                              "full_name",
                              "date_of_birth",
                              "address",
                              "provider"
                            ],
                            "description": "Champ de comparaison normalisé. `provider` n'est pas un champ utilisateur : il signale une ligne d'erreur provenant de la source."
                          },
                          "label": {
                            "type": "string",
                            "description": "Libellé d'affichage pour la ligne, par ex. `ID number`, `Full name`, `Provider`."
                          },
                          "provided": {
                            "type": "string",
                            "nullable": true,
                            "description": "Ce que l'utilisateur a saisi. `null` sur une ligne d'erreur `provider`."
                          },
                          "record": {
                            "type": "string",
                            "nullable": true,
                            "description": "Ce que contenait la source. Sur une ligne d'erreur `provider`, ceci contient le message d'erreur à la place."
                          },
                          "result": {
                            "type": "string",
                            "enum": [
                              "match",
                              "partial",
                              "no_match",
                              "error"
                            ],
                            "description": "Résultat de comparaison par champ. `error` apparaît uniquement sur une ligne `provider` et signifie que cette source n'a pas répondu ; traitez-le comme un constat sur la requête, jamais comme une non-correspondance de champ."
                          }
                        }
                      }
                    },
                    "registry_portrait": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL pré-signée de courte durée vers le portrait renvoyé par la source. Uniquement les quatre registres gouvernementaux qui en renvoient un (Afrique du Sud, Nigéria, Argentine, Panama)."
                    },
                    "face_match_score": {
                      "type": "number",
                      "nullable": true,
                      "description": "Selfie comparé au portrait du registre, 0-100. Uniquement lorsque le registre renvoie un portrait."
                    }
                  }
                },
                "wallet_verification": {
                  "type": "object",
                  "nullable": true,
                  "description": "Preuve de l'attestation. Présent uniquement lorsque `verification_method` est `wallet` ; `null` dans le cas contraire.",
                  "properties": {
                    "provider": {
                      "type": "string",
                      "description": "Identifiant de portefeuille du catalogue, par exemple `mitid`."
                    },
                    "provider_name": {
                      "type": "string",
                      "nullable": true,
                      "description": "Nom du portefeuille tel que l'utilisateur final le connaît, par exemple `MitID`."
                    },
                    "issuing_authority": {
                      "type": "string",
                      "nullable": true,
                      "description": "L'autorité derrière le portefeuille, par exemple `Danish Agency for Digital Government`."
                    },
                    "issuing_country": {
                      "type": "string",
                      "description": "Pays ISO 3166-1 alpha-3 dans lequel le portefeuille a été proposé."
                    },
                    "credential_type": {
                      "type": "string",
                      "nullable": true,
                      "description": "Attestation présentée par le portefeuille, par exemple `person_identification`."
                    },
                    "level_of_assurance": {
                      "type": "string",
                      "enum": [
                        "low",
                        "substantial",
                        "high"
                      ],
                      "nullable": true,
                      "description": "Le niveau d'assurance revendiqué par le portefeuille. Une connexion qui revendique un niveau inférieur à celui demandé échoue au lieu d'être rétrogradée."
                    },
                    "verified_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "L'instant d'authentification du portefeuille."
                    },
                    "signature_valid": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "Indique si l'assertion signée retournée par le portefeuille a été validée."
                    },
                    "attributes": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "Les attributs partagés par le portefeuille, avec pour clés celles indiquées dans l'entrée du catalogue du portefeuille."
                    },
                    "portrait": {
                      "type": "string",
                      "format": "uri",
                      "nullable": true,
                      "description": "URL pré-signée de courte durée vers le portrait partagé par le portefeuille, lorsqu'il en partage un."
                    },
                    "face_match_score": {
                      "type": "number",
                      "nullable": true,
                      "description": "Selfie comparé au portrait du portefeuille, 0-100, lorsque le portefeuille en partage un."
                    }
                  }
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Expired"
                  ],
                  "description": "Statut au niveau de la fonctionnalité de cette étape de vérification d'identité. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`."
                },
                "document_type": {
                  "type": "string",
                  "description": "Type de document d'identité"
                },
                "document_subtype": {
                  "type": "string",
                  "nullable": true,
                  "description": "Code de sous-type de document accepté issu des paramètres de document du workflow, incluant la région du document le cas échéant. Exemples : `ID_CARD_GENERIC`, `QUEENSLAND_DRIVER_LICENSE_GENERIC`."
                },
                "document_number": {
                  "type": "string",
                  "description": "Numéro d'identification du document"
                },
                "personal_number": {
                  "type": "string",
                  "description": "Numéro d'identification personnel"
                },
                "portrait_image": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image du portrait"
                },
                "front_image": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image du recto du document"
                },
                "front_video": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de la vidéo du recto du document"
                },
                "back_image": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image du verso du document"
                },
                "back_video": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de la vidéo du verso du document"
                },
                "full_front_image": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image complète du recto du document"
                },
                "full_back_image": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image complète du verso du document"
                },
                "front_image_camera_front": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image du recto du document capturée depuis la caméra frontale"
                },
                "back_image_camera_front": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image du verso du document capturée depuis la caméra frontale"
                },
                "date_of_birth": {
                  "type": "string",
                  "format": "date",
                  "description": "Date de naissance issue du document"
                },
                "age": {
                  "type": "integer",
                  "description": "Âge calculé à partir de la date de naissance"
                },
                "expiration_date": {
                  "type": "string",
                  "format": "date",
                  "description": "Date d'expiration du document"
                },
                "date_of_issue": {
                  "type": "string",
                  "format": "date",
                  "description": "Date de délivrance du document"
                },
                "issuing_state": {
                  "type": "string",
                  "description": "Code ISO de l'État émetteur"
                },
                "issuing_state_name": {
                  "type": "string",
                  "description": "Nom complet de l'État de délivrance"
                },
                "first_name": {
                  "type": "string",
                  "description": "Prénom issu du document"
                },
                "last_name": {
                  "type": "string",
                  "description": "Nom de famille extrait du document"
                },
                "full_name": {
                  "type": "string",
                  "description": "Nom complet figurant sur le document"
                },
                "gender": {
                  "type": "string",
                  "description": "Genre figurant sur le document"
                },
                "address": {
                  "type": "string",
                  "description": "Adresse brute extraite du document"
                },
                "formatted_address": {
                  "type": "string",
                  "description": "Adresse complète formatée"
                },
                "place_of_birth": {
                  "type": "string",
                  "description": "Lieu de naissance issu du document"
                },
                "marital_status": {
                  "type": "string",
                  "description": "État civil d'après le document"
                },
                "nationality": {
                  "type": "string",
                  "description": "Code ISO de nationalité"
                },
                "extra_fields": {
                  "type": "object",
                  "description": "Champs de document supplémentaires. Comprend des attributs spécifiques au document (par exemple `dl_categories`, `blood_group`, `sponsor`, `employer`, `dl_class_code_b_from`, `dl_class_code_b_to`). Les dates de validité des catégories de permis de conduire sont renvoyées sous la forme `dl_class_code_<class>_from` et `dl_class_code_<class>_to`, et les codes de restriction/information par catégorie (par exemple la colonne 12 des permis britanniques) sous la forme `dl_class_code_<class>_notes`. Lorsque le document comporte des noms, une adresse ou un lieu de naissance dans plusieurs systèmes d'écriture, cet objet inclut également les versions de ces champs dans les autres systèmes d'écriture. Le paramètre de workflow `preferred_characters` (`latin` ou `non_latin`) détermine quel système d'écriture renseigne les champs de premier niveau (`first_name`, `last_name`, `full_name`, `address`, `place_of_birth`) ; le système d'écriture opposé apparaît ici sous la forme `first_name_non_latin` / `last_name_non_latin` / `full_name_non_latin` / `middle_name_non_latin` / `address_non_latin` / `place_of_birth_non_latin` (lorsque `preferred_characters` est `latin`) ou avec un suffixe `_latin` (lorsque `preferred_characters` est `non_latin`). Les clés n'apparaissent que lorsque l'OCR extrait réellement une valeur dans un autre système d'écriture — un champ dont la valeur alternative utilise le même système d'écriture que le jeu préféré (par exemple, un champ étiqueté en cyrillique dont la valeur OCR a renvoyé des homoglyphes latins) est ignoré. Lorsque `preferred_characters` est `latin` mais que le document ne comporte que du texte non latin, Didit translittère les valeurs extraites et expose `first_name_latin` / `last_name_latin` / etc. en guise de solution de repli.",
                  "additionalProperties": true,
                  "properties": {
                    "dl_categories": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "blood_group": {
                      "type": "string",
                      "nullable": true
                    },
                    "first_name_non_latin": {
                      "type": "string",
                      "description": "Prénom dans le système d'écriture non latin lorsque `preferred_characters=latin` et qu'une version non latine est présente sur le document (par exemple `Айна` pour une pièce d'identité kirghize)."
                    },
                    "last_name_non_latin": {
                      "type": "string",
                      "description": "Nom de famille dans le système d'écriture non latin lorsque `preferred_characters=latin` et qu'une version non latine est présente sur le document."
                    },
                    "middle_name_non_latin": {
                      "type": "string",
                      "description": "Deuxième prénom / patronyme dans le système d'écriture non latin lorsque `preferred_characters=latin` et qu'une version non latine est présente sur le document."
                    },
                    "full_name_non_latin": {
                      "type": "string",
                      "description": "Nom complet composé dans le système d'écriture non latin. Reconstruit à partir des composants individuels lorsque le prénom et le nom de famille sont tous deux disponibles."
                    },
                    "address_non_latin": {
                      "type": "string",
                      "description": "Adresse dans le système d'écriture non latin lorsque `preferred_characters=latin` et qu'une version non latine est présente sur le document."
                    },
                    "place_of_birth_non_latin": {
                      "type": "string",
                      "description": "Lieu de naissance dans le système d'écriture non latin lorsque `preferred_characters=latin` et qu'une version non latine figure sur le document."
                    },
                    "first_name_latin": {
                      "type": "string",
                      "description": "Prénom en alphabet latin. Renseigné lorsque `preferred_characters=non_latin` et qu'une version latine figure sur le document, ou — en tant qu'alternative de translittération — lorsque `preferred_characters=latin` mais que le document ne comporte que du texte non latin."
                    },
                    "last_name_latin": {
                      "type": "string",
                      "description": "Nom de famille en système d'écriture latin. Mêmes règles que pour `first_name_latin`."
                    },
                    "middle_name_latin": {
                      "type": "string",
                      "description": "Deuxième prénom / patronyme en système d'écriture latin. Mêmes règles que `first_name_latin`."
                    },
                    "full_name_latin": {
                      "type": "string",
                      "description": "Nom complet composé en système d'écriture latin. Toujours reconstruit à partir des composants individuels lorsque le prénom et le nom de famille sont tous deux disponibles."
                    },
                    "address_latin": {
                      "type": "string",
                      "description": "Adresse dans le système d'écriture latin. Mêmes règles que pour `first_name_latin`."
                    },
                    "place_of_birth_latin": {
                      "type": "string",
                      "description": "Lieu de naissance en alphabet latin. Mêmes règles que `first_name_latin`."
                    }
                  }
                },
                "mrz": {
                  "type": "object",
                  "nullable": true,
                  "description": "Champs de la zone de lecture optique (MRZ) extraits du document. `null` si aucune MRZ n'a été détectée.",
                  "properties": {
                    "surname": {
                      "type": "string",
                      "example": "MARTINEZ<SANCHEZ"
                    },
                    "name": {
                      "type": "string",
                      "example": "ELENA"
                    },
                    "country": {
                      "type": "string",
                      "example": "ESP"
                    },
                    "nationality": {
                      "type": "string",
                      "example": "ESP"
                    },
                    "birth_date": {
                      "type": "string",
                      "example": "850315"
                    },
                    "expiry_date": {
                      "type": "string",
                      "example": "220821"
                    },
                    "sex": {
                      "type": "string",
                      "example": "F"
                    },
                    "document_type": {
                      "type": "string",
                      "example": "ID"
                    },
                    "document_number": {
                      "type": "string",
                      "example": "YZA123456"
                    },
                    "optional_data": {
                      "type": "string",
                      "example": "X9876543L"
                    },
                    "optional_data_2": {
                      "type": "string",
                      "example": ""
                    },
                    "birth_date_hash": {
                      "type": "string",
                      "example": "7"
                    },
                    "expiry_date_hash": {
                      "type": "string",
                      "example": "4"
                    },
                    "document_number_hash": {
                      "type": "string",
                      "example": "9"
                    },
                    "final_hash": {
                      "type": "string",
                      "example": "2"
                    },
                    "personal_number": {
                      "type": "string",
                      "example": "X9876543L"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "mrz_type": {
                      "type": "string",
                      "example": "TD1"
                    },
                    "mrz_string": {
                      "type": "string",
                      "example": "IDESPMARTINEZ<SANCHEZ<<<<<<<<<<\nYZA123456<9ESP8503157F3208214<X9876543L<<<<<<<2\nMARTINEZ<SANCHEZ<<ELENA<<<<<<<<<<"
                    },
                    "mrz_key": {
                      "type": "string",
                      "example": "YZA123456985031573208214"
                    }
                  }
                },
                "parsed_address": {
                  "type": "object",
                  "description": "Détails de l'adresse structurée",
                  "properties": {
                    "city": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "region": {
                      "type": "string"
                    },
                    "country": {
                      "type": "string",
                      "description": "Code pays à deux lettres"
                    },
                    "category": {
                      "type": "string",
                      "description": "Catégorie d'adresse (par exemple, résidentielle, commerciale)"
                    },
                    "street_1": {
                      "type": "string"
                    },
                    "street_2": {
                      "type": "string",
                      "nullable": true
                    },
                    "is_verified": {
                      "type": "boolean",
                      "description": "Indique si l'adresse a été vérifiée"
                    },
                    "postal_code": {
                      "type": "string"
                    },
                    "raw_results": {
                      "type": "object",
                      "properties": {
                        "types": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "geometry": {
                          "type": "object",
                          "properties": {
                            "location": {
                              "type": "object",
                              "properties": {
                                "lat": {
                                  "type": "number"
                                },
                                "lng": {
                                  "type": "number"
                                }
                              }
                            },
                            "viewport": {
                              "type": "object",
                              "properties": {
                                "northeast": {
                                  "type": "object",
                                  "properties": {
                                    "lat": {
                                      "type": "number"
                                    },
                                    "lng": {
                                      "type": "number"
                                    }
                                  }
                                },
                                "southwest": {
                                  "type": "object",
                                  "properties": {
                                    "lat": {
                                      "type": "number"
                                    },
                                    "lng": {
                                      "type": "number"
                                    }
                                  }
                                }
                              }
                            },
                            "location_type": {
                              "type": "string"
                            }
                          }
                        },
                        "place_id": {
                          "type": "string"
                        },
                        "formatted_address": {
                          "type": "string"
                        },
                        "navigation_points": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "location": {
                                "type": "object",
                                "properties": {
                                  "latitude": {
                                    "type": "number"
                                  },
                                  "longitude": {
                                    "type": "number"
                                  }
                                }
                              }
                            }
                          }
                        },
                        "address_components": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "types": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "long_name": {
                                "type": "string"
                              },
                              "short_name": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "address_type": {
                      "type": "string"
                    },
                    "document_location": {
                      "type": "object",
                      "properties": {
                        "latitude": {
                          "type": "number"
                        },
                        "longitude": {
                          "type": "number"
                        }
                      }
                    },
                    "formatted_address": {
                      "type": "string"
                    }
                  }
                },
                "extra_files": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uri"
                  },
                  "description": "Fichiers supplémentaires de vérification des documents"
                },
                "front_image_camera_front_face_match_score": {
                  "type": "number",
                  "nullable": true,
                  "description": "Score de correspondance faciale entre le portrait extrait de l'image du recto du document et l'image de la caméra frontale"
                },
                "back_image_camera_front_face_match_score": {
                  "type": "number",
                  "nullable": true,
                  "description": "Score de correspondance faciale entre le portrait extrait de l'image du verso du document et l'image de la caméra frontale"
                },
                "document_selfie_face_matches": {
                  "type": "array",
                  "description": "Sessions précédentes ou entrées de liste de blocage de visages dont le visage correspondait au selfie pris par la caméra avant lors de la capture du document (Silent Capture Face Search). Même format d'entrée que `liveness_checks[].matches`. `null` pour les sessions créées avant l'existence de ce champ ou lorsque la recherche n'a pas été exécutée ; un tableau vide lorsqu'elle a été exécutée et n'a rien trouvé. `match_image_url` est une URL pré-signée qui expire.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "session_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "ID de session du visage correspondant. `null` lorsque `source` vaut `imported`, `list_entry` ou `retained_template`."
                      },
                      "session_number": {
                        "type": "integer",
                        "nullable": true
                      },
                      "similarity_percentage": {
                        "type": "number",
                        "description": "Similarité faciale entre les deux images, bornée entre 0 et 100."
                      },
                      "vendor_data": {
                        "type": "string",
                        "nullable": true,
                        "description": "`vendor_data` de la session correspondante ou de l'utilisateur lié pour les visages importés et les gabarits conservés."
                      },
                      "vendor_user_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Identifiant de l'utilisateur associé pour les correspondances de type `imported` et `retained_template`, et pour les correspondances de session associées à un utilisateur. `null` pour les entrées de liste et les sessions sans utilisateur."
                      },
                      "biometric_template_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Identifiant du gabarit biométrique conservé. Renseigné uniquement lorsque `source` vaut `retained_template` ; `null` sinon."
                      },
                      "verification_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Moment où le visage correspondant a été capturé, ou lorsqu'un gabarit conservé a été créé. `null` pour les entrées de liste."
                      },
                      "user_details": {
                        "type": "object",
                        "nullable": true,
                        "description": "Données d'identité provenant de la session correspondante ou du profil utilisateur importé. Toujours `null` pour les correspondances `retained_template` et `list_entry`.",
                        "properties": {
                          "full_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "document_type": {
                            "type": "string",
                            "nullable": true
                          },
                          "document_number": {
                            "type": "string",
                            "nullable": true
                          }
                        }
                      },
                      "match_image_url": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true,
                        "description": "Image de référence pour les correspondances basées sur une image. Toujours `null` pour les correspondances `retained_template`, car les gabarits conservés ne contiennent aucune image."
                      },
                      "status": {
                        "type": "string",
                        "nullable": true,
                        "description": "Statut de cycle de vie de la session correspondante. `null` pour les sources qui ne sont pas des sessions."
                      },
                      "is_blocklisted": {
                        "type": "boolean",
                        "description": "Indique si le visage correspondant figure sur une liste de blocage."
                      },
                      "is_allowlisted": {
                        "type": "boolean",
                        "description": "Indique si le visage correspondant figure sur une liste d'autorisation."
                      },
                      "api_service": {
                        "type": "string",
                        "nullable": true,
                        "description": "Service d'API autonome de la session correspondante (par exemple `PASSIVE_LIVENESS`, `FACE_MATCH`) ; `null` pour les sessions de workflow et les sources extérieures aux sessions."
                      },
                      "source": {
                        "type": "string",
                        "enum": [
                          "session",
                          "imported",
                          "list_entry",
                          "retained_template"
                        ],
                        "description": "Origine du visage correspondant : `session`, `imported` (téléversement de visage d'un utilisateur), `list_entry` (liste d'autorisation/blocage) ou `retained_template` (un gabarit biométrique sans image stocké sur un utilisateur, répertorié sous `/v3/biometric-templates/`)."
                      }
                    }
                  },
                  "nullable": true
                },
                "front_image_quality_score": {
                  "type": "object",
                  "nullable": true,
                  "description": "Métriques de qualité pour l'image du recto du document. Chaque sous-score est compris entre 0 et 100.",
                  "properties": {
                    "focus_score": {
                      "type": "number",
                      "description": "Netteté de l'image mesurée via la variance laplacienne locale des 10 % supérieurs. Robuste face aux documents présentant de vastes arrière-plans uniformes. Des valeurs plus élevées indiquent une image plus nette et moins floue."
                    },
                    "brightness_score": {
                      "type": "number",
                      "description": "Qualité de l'éclairage de l'image. Pénalise les images trop sombres ou surexposées, la luminosité idéale se situant en milieu de plage."
                    },
                    "brightness_issue": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "too_dark",
                        "too_bright"
                      ],
                      "description": "Indique le sens du problème de luminosité lorsque le brightness_score est bas. 'ok' signifie que la luminosité est acceptable, 'too_dark' signifie que l'image est sous-exposée, 'too_bright' signifie que l'image est surexposée."
                    },
                    "is_document_fully_visible": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "true si les quatre coins du document sont entièrement visibles dans le cadre de l'image, false si un coin est coupé. Null lorsque les coordonnées des coins sont indisponibles."
                    },
                    "resolution_score": {
                      "type": "number",
                      "description": "Résolution effective de l'image basée sur le nombre total de pixels."
                    },
                    "overall_score": {
                      "type": "number",
                      "description": "Score composite pondéré des sous-scores (mise au point 45%, luminosité 30%, résolution 25%)."
                    }
                  }
                },
                "back_image_quality_score": {
                  "type": "object",
                  "nullable": true,
                  "description": "Métriques de qualité pour l'image du verso du document. Même structure que front_image_quality_score.",
                  "properties": {
                    "focus_score": {
                      "type": "number",
                      "description": "Netteté de l'image mesurée via la variance laplacienne locale des 10 % supérieurs. Robuste face aux documents présentant de vastes arrière-plans uniformes. Des valeurs plus élevées indiquent une image plus nette et moins floue."
                    },
                    "brightness_score": {
                      "type": "number",
                      "description": "Qualité de l'éclairage de l'image. Pénalise les images trop sombres ou surexposées, la luminosité idéale se situant en milieu de plage."
                    },
                    "brightness_issue": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "too_dark",
                        "too_bright"
                      ],
                      "description": "Indique le sens du problème de luminosité lorsque le brightness_score est bas. 'ok' signifie que la luminosité est acceptable, 'too_dark' signifie que l'image est sous-exposée, 'too_bright' signifie que l'image est surexposée."
                    },
                    "is_document_fully_visible": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "true si les quatre coins du document sont entièrement visibles dans le cadre de l'image, false si un coin est coupé. Null lorsque les coordonnées des coins sont indisponibles."
                    },
                    "resolution_score": {
                      "type": "number",
                      "description": "Résolution effective de l'image basée sur le nombre total de pixels."
                    },
                    "overall_score": {
                      "type": "number",
                      "description": "Score composite pondéré des sous-scores (mise au point 45%, luminosité 30%, résolution 25%)."
                    }
                  }
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement (par ex., `ID_VERIFICATION`, `NFC`, `LIVENESS`). La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module, mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true,
                        "description": "Données contextuelles supplémentaires sur l'avertissement"
                      },
                      "log_type": {
                        "type": "string",
                        "description": "Type de journal : information, avertissement ou erreur"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement (pour les workflows basés sur un graphe)"
                      }
                    }
                  },
                  "description": "Avertissements liés à la vérification des documents"
                },
                "matches": {
                  "type": "array",
                  "description": "Documents correspondants trouvés lors de la détection de doublons/liste de blocage (jusqu'à 5 correspondances)",
                  "items": {
                    "type": "object",
                    "properties": {
                      "session_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "ID de session du document correspondant"
                      },
                      "session_number": {
                        "type": "integer",
                        "description": "Numéro de session du document correspondant"
                      },
                      "vendor_data": {
                        "type": "string",
                        "nullable": true,
                        "description": "Données fournisseur associées à la session correspondante"
                      },
                      "verification_date": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Date à laquelle la session correspondante a été vérifiée"
                      },
                      "user_details": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Nom complet extrait du document correspondant"
                          },
                          "document_type": {
                            "type": "string",
                            "description": "Type du document correspondant"
                          },
                          "document_number": {
                            "type": "string",
                            "description": "Numéro de document du document correspondant"
                          }
                        }
                      },
                      "status": {
                        "type": "string",
                        "description": "Statut de la session correspondante"
                      },
                      "is_blocklisted": {
                        "type": "boolean",
                        "description": "Indique si le document correspondant figure sur une liste de blocage"
                      },
                      "api_service": {
                        "type": "string",
                        "nullable": true,
                        "description": "Type de service d'API de la session correspondante"
                      },
                      "front_image_url": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true,
                        "description": "URL de l'image du recto du document correspondant"
                      }
                    }
                  }
                },
                "document_liveness": {
                  "type": "object",
                  "nullable": true,
                  "description": "Scores de détection du vivant du document par type de fraude, signalés, qu'un avertissement se soit déclenché ou non, afin qu'un document approuvé puisse toujours faire l'objet d'un audit. `null` lorsque la vérification n'a pas été exécutée.",
                  "properties": {
                    "portrait_replace": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "score": {
                          "type": "number",
                          "nullable": true,
                          "description": "Probabilité que le document soit authentique pour ce type de fraude, 0-100 (plus le score est élevé, plus le document est probablement authentique). La valeur la plus basse des deux faces : celle utilisée pour la décision. `null` lorsqu'aucune des faces n'a produit de score utilisable."
                        },
                        "front": {
                          "type": "number",
                          "nullable": true,
                          "description": "Score pour le recto ; `null` s'il n'a pas été capturé ou si le score a été supprimé."
                        },
                        "back": {
                          "type": "number",
                          "nullable": true,
                          "description": "Score pour le verso ; `null` s'il n'a pas été capturé ou si le score a été supprimé."
                        },
                        "decline_threshold": {
                          "type": "number",
                          "nullable": true,
                          "description": "Le seuil de refus enregistré lors de l'évaluation de ce document. Les modifications ultérieures du workflow ne le changent pas. Null lorsqu'aucun élément probant de l'évaluation historique n'est disponible."
                        },
                        "review_threshold": {
                          "type": "number",
                          "nullable": true,
                          "description": "Le seuil d'examen enregistré lors de l'évaluation de ce document. Les modifications ultérieures du workflow ne le changent pas. Null lorsque les preuves d'évaluation historiques ne sont pas disponibles."
                        },
                        "bucket": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "approve",
                            "review",
                            "decline",
                            null
                          ],
                          "description": "La catégorie de type de fraude enregistrée au moment de l'évaluation. Null lorsqu'il n'y a aucun score utilisable, que la vérification n'a pas été appliquée ou que les éléments de preuve d'évaluation historiques sont indisponibles. Les modifications ultérieures du workflow ne la changent pas."
                        }
                      }
                    },
                    "printed_copy": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "score": {
                          "type": "number",
                          "nullable": true,
                          "description": "Probabilité que le document soit authentique pour ce type de fraude, 0-100 (plus le score est élevé, plus le document est probablement authentique). La valeur la plus basse des deux faces : celle utilisée pour la décision. `null` lorsqu'aucune des faces n'a produit de score utilisable."
                        },
                        "front": {
                          "type": "number",
                          "nullable": true,
                          "description": "Score pour le recto ; `null` s'il n'a pas été capturé ou si le score a été supprimé."
                        },
                        "back": {
                          "type": "number",
                          "nullable": true,
                          "description": "Score pour le verso ; `null` s'il n'a pas été capturé ou si le score a été supprimé."
                        },
                        "decline_threshold": {
                          "type": "number",
                          "nullable": true,
                          "description": "Le seuil de refus enregistré lors de l'évaluation de ce document. Les modifications ultérieures du workflow ne le changent pas. Null lorsqu'aucun élément probant de l'évaluation historique n'est disponible."
                        },
                        "review_threshold": {
                          "type": "number",
                          "nullable": true,
                          "description": "Le seuil d'examen enregistré lors de l'évaluation de ce document. Les modifications ultérieures du workflow ne le changent pas. Null lorsque les preuves d'évaluation historiques ne sont pas disponibles."
                        },
                        "bucket": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "approve",
                            "review",
                            "decline",
                            null
                          ],
                          "description": "La catégorie de type de fraude enregistrée au moment de l'évaluation. Null lorsqu'il n'y a aucun score utilisable, que la vérification n'a pas été appliquée ou que les éléments de preuve d'évaluation historiques sont indisponibles. Les modifications ultérieures du workflow ne la changent pas."
                        }
                      }
                    },
                    "screen_replay": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "score": {
                          "type": "number",
                          "nullable": true,
                          "description": "Probabilité que le document soit authentique pour ce type de fraude, 0-100 (plus le score est élevé, plus le document est probablement authentique). La valeur la plus basse des deux faces : celle utilisée pour la décision. `null` lorsqu'aucune des faces n'a produit de score utilisable."
                        },
                        "front": {
                          "type": "number",
                          "nullable": true,
                          "description": "Score pour le recto ; `null` s'il n'a pas été capturé ou si le score a été supprimé."
                        },
                        "back": {
                          "type": "number",
                          "nullable": true,
                          "description": "Score pour le verso ; `null` s'il n'a pas été capturé ou si le score a été supprimé."
                        },
                        "decline_threshold": {
                          "type": "number",
                          "nullable": true,
                          "description": "Le seuil de refus enregistré lors de l'évaluation de ce document. Les modifications ultérieures du workflow ne le changent pas. Null lorsqu'aucun élément probant de l'évaluation historique n'est disponible."
                        },
                        "review_threshold": {
                          "type": "number",
                          "nullable": true,
                          "description": "Le seuil d'examen enregistré lors de l'évaluation de ce document. Les modifications ultérieures du workflow ne le changent pas. Null lorsque les preuves d'évaluation historiques ne sont pas disponibles."
                        },
                        "bucket": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "approve",
                            "review",
                            "decline",
                            null
                          ],
                          "description": "La catégorie de type de fraude enregistrée au moment de l'évaluation. Null lorsqu'il n'y a aucun score utilisable, que la vérification n'a pas été appliquée ou que les éléments de preuve d'évaluation historiques sont indisponibles. Les modifications ultérieures du workflow ne la changent pas."
                        }
                      }
                    }
                  }
                },
                "address_validation": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/AddressValidationResult"
                    }
                  ],
                  "nullable": true,
                  "description": "Validation de l'adresse imprimée sur ce document : indique si elle existe et sa forme normalisée, telle que lue sur le document (une correction ultérieure de `address` ne relance pas la validation). Présent lorsque cette étape de vérification d'identité a activé le module complémentaire Validation d'adresse ; `null` dans le cas contraire."
                },
                "region": {
                  "type": "string",
                  "nullable": true,
                  "description": "Région ou État du pays de délivrance du document, lorsque le document en mentionne un."
                },
                "extracted_data": {
                  "type": "object",
                  "nullable": true,
                  "additionalProperties": true,
                  "description": "Instantané des données extraites du document qui ont été présentées à la personne pour vérification, conservées aux côtés des valeurs confirmées afin que vous puissiez comparer ce qui a été lu avec ce que la personne a confirmé. `null` lorsque la personne n'a pas été invitée à vérifier."
                },
                "barcodes": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "description": "Données lues à partir des codes-barres du document. Vide lorsque le document n'en comporte aucun ou qu'aucun n'a pu être lu."
                }
              }
            }
          },
          "nfc_skip_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "USER_SKIPPED",
              "DOCUMENT_WITHOUT_CHIP",
              "CHIP_CERTIFICATE_UNAVAILABLE",
              "DEVICE_WITHOUT_NFC",
              "INTEGRATION_WITHOUT_NFC_ACCESS",
              "MRZ_KEY_UNAVAILABLE",
              "JPKI_UNAVAILABLE"
            ],
            "description": "Raison pour laquelle la vérification de la puce NFC n'a pas été exécutée, renseignée chaque fois que le workflow comprend une étape NFC. `null` tant que le NFC est en attente ou lorsque la puce a effectivement été lue. Valeurs : `USER_SKIPPED` - l'utilisateur a choisi d'ignorer l'étape sur un appareil compatible NFC (autorisé par `allow_nfc_skip`) ; `DOCUMENT_WITHOUT_CHIP` - le document ne possède pas de puce NFC lisible (il ne s'agit pas d'un document électronique ICAO 9303) ; `CHIP_CERTIFICATE_UNAVAILABLE` - le certificat de signature du pays de délivrance (CSCA) couvrant la période d'émission du document n'est pas disponible, la signature de la puce ne peut donc pas être vérifiée ; `DEVICE_WITHOUT_NFC` - l'appareil a signalé l'absence de lecteur NFC ; `INTEGRATION_WITHOUT_NFC_ACCESS` - la vérification s'est exécutée sans SDK natif (par exemple dans un navigateur web), qui n'a pas accès au lecteur NFC du téléphone ; `MRZ_KEY_UNAVAILABLE` - la clé d'accès à la puce n'a pas pu être dérivée de la MRZ du document ; `JPKI_UNAVAILABLE` - le document est une carte My Number japonaise, dont la puce est lue via JPKI, et JPKI n'était pas disponible pour cette vérification : il n'est pas activé, ou le SDK natif de l'application ne peut pas lire les cartes My Number."
          },
          "nfc_verifications": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports NFC / passeport électronique** produits par les étapes NFC dans le graphe du workflow. **Il s'agit toujours d'un tableau JSON, jamais d'un objet `nfc` singulier** — lisez `nfc_verifications[0]` et itérez si votre workflow peut effectuer une vérification NFC plus d'une fois. `null` jusqu'à ce qu'au moins une étape NFC ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, le `status` au niveau de la fonctionnalité, `chip_protocol`, `chip_data`, `authenticity` (intégrité SOD + DG), `certificate_summary` et `warnings[]`. Une carte My Number japonaise est lue via JPKI au lieu de l'OACI 9303 : son élément a `chip_protocol: \"jpki\"`, contient ses preuves sous `jpki`, et laisse les champs OACI à `null`. Lorsque l'étape NFC a été ignorée avant même d'avoir pu être proposée (document sans puce, certificat manquant, aucune capacité NFC signalée, clé MRZ illisible, JPKI indisponible pour une carte My Number), cela reste `null` et `nfc_skip_reason` en explique la raison ; un contournement au niveau de l'étape elle-même (l'utilisateur a appuyé sur ignorer, ou le lecteur s'est révélé indisponible au moment de la lecture) produit tout de même un rapport avec `is_nfc_skipped: true`.",
            "items": {
              "type": "object",
              "description": "Un rapport NFC : le rapport complet pour une seule lecture de puce (une puce de passeport électronique ou d'eID OACI 9303, ou une My Number Card japonaise lue via JPKI).",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "ID de nœud du graphe de workflow de l'étape NFC ayant produit ce rapport. Utilisez-le pour corréler le rapport avec la définition du workflow."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Resub Requested"
                  ],
                  "description": "Statut au niveau de la fonctionnalité de cette étape NFC. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`."
                },
                "is_nfc_skipped": {
                  "type": "boolean",
                  "description": "`true` lorsque cette étape NFC a été explicitement ignorée au lieu d'être lue ; `skip_reason` en indique la raison."
                },
                "skip_reason": {
                  "type": "string",
                  "nullable": true,
                  "enum": [
                    "USER_SKIPPED",
                    "DOCUMENT_WITHOUT_CHIP",
                    "CHIP_CERTIFICATE_UNAVAILABLE",
                    "DEVICE_WITHOUT_NFC",
                    "INTEGRATION_WITHOUT_NFC_ACCESS",
                    "MRZ_KEY_UNAVAILABLE",
                    "JPKI_UNAVAILABLE"
                  ],
                  "description": "Raison pour laquelle cette étape NFC a été ignorée. Défini uniquement lorsque `is_nfc_skipped` est `true`. Même taxonomie que le `nfc_skip_reason` au niveau de la session, qui couvre en plus les cas où le NFC n'a généré aucun rapport."
                },
                "chip_protocol": {
                  "type": "string",
                  "enum": [
                    "icao",
                    "jpki"
                  ],
                  "description": "Manière dont l'étape NFC lit la puce. `icao` : puce de passeport électronique ou de carte d'identité électronique ICAO 9303, ouverte avec la clé d'accès issue de la MRZ. `jpki` : Japan My Number Card, où la carte signe un défi à usage unique après la saisie par le titulaire du code PIN de sa carte dans un SDK natif ; le résultat se trouve sous `jpki`. Également défini pour les étapes ignorées, afin de pouvoir distinguer une lecture de My Number Card ignorée."
                },
                "jpki": {
                  "type": "object",
                  "nullable": true,
                  "description": "Ce qu'une lecture de carte My Number japonaise via JPKI a prouvé. Présent lorsque `chip_protocol` vaut `jpki` et que la carte a été lue. `null` pour les puces ICAO, pour les étapes ignorées, et lorsque l'étape NFC s'est terminée sans qu'aucune carte ne soit lue (ce cas génère `JPKI_SIGNATURE_INVALID`). Ne contient jamais les certificats, leurs numéros de série, les signatures ou le numéro My Number à 12 chiffres.",
                  "properties": {
                    "certificate_types": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "user_authentication",
                          "signature"
                        ]
                      },
                      "description": "Les certificats de carte lus. `user_authentication` (code PIN à 4 chiffres) est toujours lu ; `signature` (code PIN de signature) est lu lorsque le paramètre `jpki_request_attributes` du nœud NFC est activé."
                    },
                    "chain_valid": {
                      "type": "boolean",
                      "description": "`true` lorsque chaque certificat lu remonte jusqu'à l'autorité de certification JPKI, se situe dans sa période de validité et est un certificat My Number Card de son type respectif."
                    },
                    "signature_valid": {
                      "type": "boolean",
                      "description": "`true` lorsque chaque signature effectuée par la carte sur le challenge à usage unique est vérifiée. La carte ne signe qu'après la saisie de son code PIN, ce qui prouve la possession de la carte et la connaissance du code PIN."
                    },
                    "revocation_status": {
                      "type": "string",
                      "enum": [
                        "good",
                        "revoked",
                        "unchecked"
                      ],
                      "description": "`good` lorsque la vérification de révocation a confirmé que chaque certificat est valide, `revoked` lorsqu'au moins un certificat est révoqué (par exemple une carte signalée perdue), `unchecked` lorsqu'aucune réponse de révocation n'était disponible. `unchecked` n'est jamais traité comme `good` : le paramètre `jpki_revocation_unchecked_action` du nœud NFC détermine le résultat (`REVIEW` par défaut)."
                    },
                    "ca_generation": {
                      "type": "string",
                      "nullable": true,
                      "description": "Génération de l'autorité de certification JPKI ayant émis les certificats, par exemple `2023`. `null` si aucun certificat ne remonte à l'une d'elles."
                    },
                    "certificate_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "La date d'expiration la plus proche parmi les certificats lus."
                    },
                    "certificates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Ce qu'un certificat lu sur la carte a prouvé. Jamais le certificat lui-même ni son numéro de série.",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "user_authentication",
                              "signature"
                            ],
                            "description": "Quel certificat de carte cette entrée décrit."
                          },
                          "chain_valid": {
                            "type": "boolean",
                            "description": "`true` lorsque le certificat remonte jusqu'à l'autorité de certification JPKI de son type, se situe dans sa période de validité et est un certificat My Number Card de ce type."
                          },
                          "signature_valid": {
                            "type": "boolean",
                            "description": "`true` lorsque la signature de la carte sur le challenge à usage unique est vérifiée par rapport à ce certificat."
                          },
                          "ca_generation": {
                            "type": "string",
                            "nullable": true,
                            "description": "Génération de l'autorité de certification JPKI ayant émis le certificat, par exemple `2023`. `null` si aucun émetteur de confiance n'a été trouvé."
                          },
                          "not_valid_before": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Début de la période de validité du certificat. `null` lorsque le certificat n'a pas pu être lu."
                          },
                          "not_valid_after": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Fin de la période de validité du certificat. `null` lorsque le certificat n'a pas pu être lu."
                          },
                          "failure": {
                            "type": "string",
                            "nullable": true,
                            "enum": [
                              "unreadable_certificate",
                              "untrusted_issuer",
                              "expired",
                              "not_yet_valid",
                              "wrong_policy",
                              "key_usage",
                              null
                            ],
                            "description": "Raison pour laquelle `chain_valid` est `false` : `unreadable_certificate`, `untrusted_issuer` (non émis par l'autorité de certification JPKI de ce type), `expired`, `not_yet_valid`, `wrong_policy` (il ne s'agit pas d'un certificat de carte My Number de ce type) ou `key_usage` (la clé ne peut pas signer). `null` lorsque la chaîne est valide."
                          }
                        }
                      },
                      "description": "Résultats par certificat, une entrée par certificat lu."
                    },
                    "attributes": {
                      "type": "object",
                      "nullable": true,
                      "description": "Les données du titulaire issues du certificat de signature, une fois sa chaîne valide. `null` lorsque le certificat de signature n'a pas été demandé ou ne s'est pas rattaché à l'autorité de certification JPKI.",
                      "properties": {
                        "full_name": {
                          "type": "string",
                          "nullable": true,
                          "description": "Nom tel qu'enregistré, généralement en système d'écriture japonais."
                        },
                        "date_of_birth": {
                          "type": "string",
                          "format": "date",
                          "nullable": true,
                          "description": "Date de naissance, `YYYY-MM-DD`. `null` lorsque la date enregistrée est incomplète."
                        },
                        "gender": {
                          "type": "string",
                          "nullable": true,
                          "enum": [
                            "M",
                            "F",
                            null
                          ],
                          "description": "`M`, `F` ou `null` lorsqu'il n'est pas enregistré."
                        },
                        "address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Adresse enregistrée."
                        },
                        "name_substitute_characters": {
                          "type": "string",
                          "nullable": true,
                          "description": "Chaîne de positions indiquant les caractères de `full_name` qui ont été remplacés par un substitut parce que le caractère d'origine ne fait pas partie du jeu de caractères standard. `null` si aucun n'a été remplacé."
                        },
                        "address_substitute_characters": {
                          "type": "string",
                          "nullable": true,
                          "description": "Chaîne de positions indiquant les caractères de substitution dans `address`, comme pour `name_substitute_characters`."
                        }
                      }
                    },
                    "attributes_match_ocr": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "`true` lorsque les attributs correspondent aux données lues à partir de la photo de la même carte, `false` lorsqu'un attribut diffère (`JPKI_AND_OCR_DATA_NOT_SAME`), `null` lorsque rien n'a pu être comparé, y compris dès lors que `attributes` est `null`."
                    },
                    "mismatched_attributes": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "full_name",
                          "date_of_birth",
                          "gender",
                          "address"
                        ]
                      },
                      "description": "Noms des attributs qui diffèrent des données de la photo, jamais leurs valeurs. Vide lorsque tout ce qui est comparé correspond."
                    }
                  }
                },
                "portrait_image": {
                  "type": "string",
                  "format": "uri",
                  "nullable": true,
                  "description": "URL pré-signée vers le portrait lu depuis la puce (ICAO DG2). `null` pour une lecture JPKI (`chip_protocol: \"jpki\"`) et pour les étapes ignorées."
                },
                "signature_image": {
                  "type": "string",
                  "format": "uri",
                  "nullable": true,
                  "description": "URL pré-signée vers l'image de la signature du titulaire lue depuis la puce (ICAO DG7), lorsque la puce en contient une. `null` pour une lecture JPKI (`chip_protocol: \"jpki\"`) et pour les étapes ignorées."
                },
                "chip_data": {
                  "type": "object",
                  "nullable": true,
                  "description": "Données personnelles analysées à partir des Data Groups de la puce OACI. `null` pour une lecture JPKI (`chip_protocol: \"jpki\"`) et pour les étapes ignorées.",
                  "properties": {
                    "document_type": {
                      "type": "string"
                    },
                    "issuing_country": {
                      "type": "string"
                    },
                    "document_number": {
                      "type": "string"
                    },
                    "expiration_date": {
                      "type": "string",
                      "format": "date"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "last_name": {
                      "type": "string"
                    },
                    "birth_date": {
                      "type": "string",
                      "format": "date"
                    },
                    "gender": {
                      "type": "string"
                    },
                    "nationality": {
                      "type": "string"
                    },
                    "address": {
                      "type": "string"
                    },
                    "place_of_birth": {
                      "type": "string"
                    }
                  }
                },
                "authenticity": {
                  "type": "object",
                  "nullable": true,
                  "description": "Authentification passive OACI : signature SOD (`sod_integrity`) et hachages Data Group (`dg_integrity`). `null` pour une lecture JPKI, qui renvoie sa preuve sous `jpki`.",
                  "properties": {
                    "sod_integrity": {
                      "type": "boolean"
                    },
                    "dg_integrity": {
                      "type": "boolean"
                    }
                  }
                },
                "certificate_summary": {
                  "type": "object",
                  "nullable": true,
                  "description": "Résumé du certificat du signataire de document (Document Signer Certificate) OACI. `null` pour une lecture JPKI (`chip_protocol: \"jpki\"`) et pour les étapes ignorées.",
                  "properties": {
                    "issuer": {
                      "type": "string"
                    },
                    "subject": {
                      "type": "string"
                    },
                    "serial_number": {
                      "type": "string"
                    },
                    "not_valid_after": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "not_valid_before": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "log_type": {
                        "type": "string"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                      }
                    }
                  }
                }
              }
            }
          },
          "liveness_checks": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de détection du vivant** produits par les étapes de détection du vivant dans le graphe du workflow. Toujours un tableau JSON — jamais un objet `liveness` singulier. `null` jusqu'à ce qu'au moins une étape de détection du vivant ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, le `status` au niveau de la fonctionnalité, `method`, `score`, `reference_image`, `video_url`, l'`age_estimation` facultative, les `matches[]` entre sessions et `warnings[]`.",
            "items": {
              "type": "object",
              "description": "Un rapport de détection du vivant — le rapport complet pour un seul passage de détection du vivant.",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "ID de nœud du graphe de workflow de l'étape de détection du vivant ayant produit ce rapport."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Resub Requested"
                  ],
                  "description": "Statut au niveau de la fonctionnalité de cette étape de détection du vivant. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`."
                },
                "method": {
                  "type": "string",
                  "description": "Méthode utilisée pour la détection du vivant"
                },
                "score": {
                  "type": "number",
                  "description": "Score de confiance du contrôle de détection du vivant"
                },
                "reference_image": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image de référence utilisée"
                },
                "video_url": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de la vidéo de détection du vivant"
                },
                "age_estimation": {
                  "type": "number",
                  "description": "Âge estimé de la personne"
                },
                "matches": {
                  "type": "array",
                  "description": "Visages similaires trouvés par la recherche de visages en doublon (meilleures correspondances, entrées sur liste de blocage/liste autorisée en premier). La propriété `source` de chaque entrée indique la provenance du visage correspondant : `session` (une autre session de vérification), `imported` (un visage téléversé pour un utilisateur du fournisseur), `list_entry` (un visage issu d'une liste de blocage/liste autorisée gérée par l'organisation) ou `retained_template` (un gabarit biométrique sans image stocké sur un utilisateur, listé sous `/v3/biometric-templates/`). `session_id`, `session_number`, `status` et `api_service` sont `null` pour les sources autres que les sessions. Les correspondances `imported` renseignent tout de même `vendor_data`, `verification_date` et — si l'utilisateur du fournisseur a un nom enregistré — `user_details` (avec `full_name` uniquement) à partir de la fiche de l'utilisateur du fournisseur ; les correspondances `retained_template` renseignent `vendor_user_id`, `vendor_data`, `biometric_template_id` et `verification_date`, tandis que leurs champs d'image et d'identité sont `null` ; les correspondances `list_entry` renvoient tous ces champs à `null`.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "session_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "ID de session du visage correspondant. `null` lorsque `source` vaut `imported`, `list_entry` ou `retained_template`."
                      },
                      "session_number": {
                        "type": "integer",
                        "nullable": true
                      },
                      "similarity_percentage": {
                        "type": "number",
                        "description": "Similarité faciale entre les deux images, bornée entre 0 et 100."
                      },
                      "vendor_data": {
                        "type": "string",
                        "nullable": true,
                        "description": "`vendor_data` de la session correspondante ou de l'utilisateur lié pour les visages importés et les gabarits conservés."
                      },
                      "vendor_user_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Identifiant de l'utilisateur associé pour les correspondances de type `imported` et `retained_template`, et pour les correspondances de session associées à un utilisateur. `null` pour les entrées de liste et les sessions sans utilisateur."
                      },
                      "biometric_template_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Identifiant du gabarit biométrique conservé. Renseigné uniquement lorsque `source` vaut `retained_template` ; `null` sinon."
                      },
                      "verification_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Moment où le visage correspondant a été capturé, ou lorsqu'un gabarit conservé a été créé. `null` pour les entrées de liste."
                      },
                      "user_details": {
                        "type": "object",
                        "nullable": true,
                        "description": "Données d'identité provenant de la session correspondante ou du profil utilisateur importé. Toujours `null` pour les correspondances `retained_template` et `list_entry`.",
                        "properties": {
                          "full_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "document_type": {
                            "type": "string",
                            "nullable": true
                          },
                          "document_number": {
                            "type": "string",
                            "nullable": true
                          }
                        }
                      },
                      "match_image_url": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true,
                        "description": "Image de référence pour les correspondances basées sur une image. Toujours `null` pour les correspondances `retained_template`, car les gabarits conservés ne contiennent aucune image."
                      },
                      "status": {
                        "type": "string",
                        "nullable": true,
                        "description": "Statut de cycle de vie de la session correspondante. `null` pour les sources qui ne sont pas des sessions."
                      },
                      "is_blocklisted": {
                        "type": "boolean",
                        "description": "Indique si le visage correspondant figure sur une liste de blocage."
                      },
                      "is_allowlisted": {
                        "type": "boolean",
                        "description": "Indique si le visage correspondant figure sur une liste d'autorisation."
                      },
                      "api_service": {
                        "type": "string",
                        "nullable": true,
                        "description": "Service d'API autonome de la session correspondante (par exemple `PASSIVE_LIVENESS`, `FACE_MATCH`) ; `null` pour les sessions de workflow et les sources extérieures aux sessions."
                      },
                      "source": {
                        "type": "string",
                        "enum": [
                          "session",
                          "imported",
                          "list_entry",
                          "retained_template"
                        ],
                        "description": "Origine du visage correspondant : `session`, `imported` (téléversement de visage d'un utilisateur), `list_entry` (liste d'autorisation/blocage) ou `retained_template` (un gabarit biométrique sans image stocké sur un utilisateur, répertorié sous `/v3/biometric-templates/`)."
                      }
                    }
                  }
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "log_type": {
                        "type": "string"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                      }
                    }
                  }
                },
                "face_quality": {
                  "type": "number",
                  "nullable": true,
                  "description": "Score de qualité de l'image du visage (0-100%). Disponible uniquement pour la détection du vivant passive."
                },
                "face_luminance": {
                  "type": "number",
                  "nullable": true,
                  "description": "Score de luminance/luminosité du visage (0-100 %). Disponible uniquement pour la détection du vivant passive."
                }
              }
            }
          },
          "face_matches": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de correspondance faciale** produits par les étapes de correspondance faciale dans le graphe du workflow. Toujours un tableau JSON — jamais un objet `face_match` singulier. `null` jusqu'à ce qu'au moins une étape de correspondance faciale ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, le `status` au niveau de la fonctionnalité, le `score` de similarité, `source_image`, `target_image` et `warnings[]`.",
            "items": {
              "type": "object",
              "description": "Un rapport de correspondance faciale — le rapport complet.",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "ID de nœud du graphe de workflow de l'étape de correspondance faciale ayant produit ce rapport."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Resub Requested"
                  ],
                  "description": "Statut au niveau de la fonctionnalité de cette étape de correspondance faciale. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`."
                },
                "score": {
                  "type": "number",
                  "description": "Score de confiance de la correspondance faciale"
                },
                "source_image_session_id": {
                  "type": "string",
                  "format": "uuid",
                  "nullable": true,
                  "description": "ID de session sous lequel le portrait source (de référence) est stocké. Dans les flux d'authentification biométrique, il s'agit de l'identifiant propre à la session (le portrait soumis est stocké sous la nouvelle session). `null` lorsque l'image source est le portrait du document de cette même session."
                },
                "source_image": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image source utilisée pour la comparaison"
                },
                "target_image": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL de l'image cible utilisée pour la comparaison"
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "log_type": {
                        "type": "string"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                      }
                    }
                  },
                  "description": "Avertissements de vérification de la correspondance faciale"
                },
                "face_coverage": {
                  "type": "object",
                  "nullable": true,
                  "description": "Indique si les yeux, la bouche et le visage sont masqués sur l'image capturée. Renvoyé uniquement par `GET /v3/session/{sessionId}/decision/` ; ne fait pas partie des payloads de webhook. `null` lorsqu'aucune mesure de couverture n'existe.",
                  "properties": {
                    "eyes": {
                      "type": "object",
                      "properties": {
                        "covered": {
                          "type": "boolean",
                          "nullable": true
                        },
                        "calibrated": {
                          "type": "boolean",
                          "nullable": true,
                          "description": "`false` signifie que le relevé est uniquement une preuve secondaire et qu'aucun avertissement n'agit dessus."
                        },
                        "visibility_score": {
                          "type": "number",
                          "nullable": true
                        }
                      }
                    },
                    "mouth": {
                      "type": "object",
                      "properties": {
                        "covered": {
                          "type": "boolean",
                          "nullable": true
                        },
                        "calibrated": {
                          "type": "boolean",
                          "nullable": true,
                          "description": "`false` signifie que le relevé est uniquement une preuve secondaire et qu'aucun avertissement n'agit dessus."
                        },
                        "visibility_score": {
                          "type": "number",
                          "nullable": true
                        }
                      }
                    },
                    "face": {
                      "type": "object",
                      "properties": {
                        "covered": {
                          "type": "boolean",
                          "nullable": true
                        },
                        "calibrated": {
                          "type": "boolean",
                          "nullable": true,
                          "description": "`false` signifie que le relevé est uniquement une preuve secondaire et qu'aucun avertissement n'agit dessus."
                        },
                        "visibility_score": {
                          "type": "number",
                          "nullable": true
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "phone_verifications": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de vérification du téléphone** — toujours un tableau JSON, jamais un objet `phone` singulier. `null` jusqu'à ce qu'au moins une étape de vérification du téléphone ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, le `status` au niveau de la fonctionnalité, le numéro de téléphone et les métadonnées de pays, `lifecycle[]`, `matches[]` et `warnings[]`.",
            "items": {
              "type": "object",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "Identifiant unique de cette étape de téléphone dans le graphe de workflow."
                },
                "status": {
                  "type": "string",
                  "description": "Statut au niveau de la fonctionnalité de cette étape de vérification du téléphone. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`.",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Expired"
                  ]
                },
                "phone_number_prefix": {
                  "type": "string",
                  "description": "Préfixe de l'indicatif téléphonique du pays"
                },
                "phone_number": {
                  "type": "string",
                  "description": "Numéro de téléphone sans indicatif pays"
                },
                "full_number": {
                  "type": "string",
                  "description": "Numéro de téléphone complet avec indicatif pays"
                },
                "country_code": {
                  "type": "string",
                  "description": "Code pays à deux lettres (ISO 3166-1 alpha-2)"
                },
                "country_name": {
                  "type": "string",
                  "description": "Nom complet du pays"
                },
                "carrier": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Nom de l'opérateur téléphonique"
                    },
                    "type": {
                      "type": "string",
                      "description": "Type de ligne téléphonique (mobile, fixe, etc.)"
                    }
                  }
                },
                "is_disposable": {
                  "type": "boolean",
                  "description": "Indique si le numéro de téléphone provient d'un service jetable"
                },
                "is_virtual": {
                  "type": "boolean",
                  "description": "Indique si le numéro de téléphone est virtuel"
                },
                "verification_method": {
                  "type": "string",
                  "description": "Méthode utilisée pour vérifier le numéro de téléphone"
                },
                "verification_attempts": {
                  "type": "integer",
                  "description": "Nombre de tentatives de vérification effectuées"
                },
                "verified_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Horodatage de la vérification du téléphone"
                },
                "lifecycle": {
                  "type": "array",
                  "description": "Liste chronologique des événements du cycle de vie de la vérification de téléphone.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string"
                      },
                      "timestamp": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "details": {
                        "type": "object",
                        "nullable": true,
                        "description": "Payload spécifique à l'événement. Les événements d'envoi contiennent `status`, `reason`, `channel`, `actual_channel` ; les événements de livraison contiennent `channel`, `status` ; les événements de vérification de code contiennent `code_tried`, `status` ; les événements d'état final contiennent `reason` — ou `null` lorsqu'il n'y a aucune raison à signaler (par ex. `PHONE_VERIFICATION_APPROVED`).",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "reason": {
                            "type": "string",
                            "nullable": true
                          },
                          "channel": {
                            "type": "string",
                            "nullable": true
                          },
                          "actual_channel": {
                            "type": "string",
                            "nullable": true
                          },
                          "code_tried": {
                            "type": "string"
                          }
                        }
                      },
                      "fee": {
                        "type": "number"
                      }
                    }
                  }
                },
                "warnings": {
                  "type": "array",
                  "description": "Liste des avertissements liés à la vérification du téléphone",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "log_type": {
                        "type": "string"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                      }
                    }
                  }
                },
                "matches": {
                  "type": "array",
                  "description": "Correspondances trouvées pour ce numéro de téléphone. Chaque correspondance a une `source` : `session` (une autre session de vérification dans votre application correspondait au même numéro, renvoyée avec `session_id`/`session_number`/`vendor_data`/`verification_date`) ou `list_entry` (le numéro figure sur une liste d'autorisation/de blocage gérée par l'organisation — voir `/management-api/lists/overview`). Les correspondances inter-sessions utilisent des `vendor_data` différents et sont plafonnées à 5.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "session_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                      },
                      "session_number": {
                        "type": "integer",
                        "nullable": true
                      },
                      "vendor_data": {
                        "type": "string",
                        "nullable": true
                      },
                      "verification_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                      },
                      "phone_number": {
                        "type": "string"
                      },
                      "status": {
                        "type": "string",
                        "nullable": true
                      },
                      "is_blocklisted": {
                        "type": "boolean"
                      },
                      "api_service": {
                        "type": "string",
                        "nullable": true
                      },
                      "source": {
                        "type": "string",
                        "enum": [
                          "session",
                          "list_entry"
                        ],
                        "description": "Origine de cette correspondance. `session` indique qu'une autre session de vérification dans votre application correspondait à cette valeur. `list_entry` indique que la valeur correspondait à une liste gérée par l'organisation (liste d'autorisation/liste de blocage) — consultez la vue d'ensemble des listes de l'API de gestion sur `/management-api/lists/overview` pour savoir comment gérer ces listes."
                      }
                    }
                  }
                },
                "phone_intelligence": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PhoneIntelligence"
                    }
                  ],
                  "description": "Signaux d'intelligence téléphonique. Présent uniquement lorsque l'add-on d'intelligence téléphonique a été exécuté pour ce numéro."
                },
                "phone_social": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PhoneSocialFootprint"
                    }
                  ],
                  "description": "Empreinte sociale du numéro. Présent uniquement lorsque le module complémentaire d'empreinte sociale a été exécuté pour ce numéro."
                }
              }
            }
          },
          "email_verifications": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de vérification d'e-mail** — toujours un tableau JSON, jamais un objet `email` singulier. `null` jusqu'à ce qu'au moins une étape d'e-mail ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, le `status` au niveau de la fonctionnalité, l'adresse e-mail, les données de compromission, `lifecycle[]`, `matches[]` et `warnings[]`.",
            "items": {
              "type": "object",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "Identifiant unique de cette étape d'e-mail dans le graphe de workflow."
                },
                "status": {
                  "type": "string",
                  "description": "Statut au niveau de la fonctionnalité de cette étape de vérification de l'e-mail. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`.",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Expired"
                  ]
                },
                "email": {
                  "type": "string",
                  "description": "L'adresse e-mail en cours de vérification"
                },
                "is_breached": {
                  "type": "boolean",
                  "description": "Indique si l'e-mail a été trouvé dans des violations de données connues"
                },
                "breaches": {
                  "type": "array",
                  "description": "Liste des fuites de données connues dans lesquelles cet e-mail a été trouvé",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "Nom de la violation"
                      },
                      "domain": {
                        "type": "string",
                        "description": "Domaine concerné par la violation"
                      },
                      "logo_path": {
                        "type": "string",
                        "description": "URL du logo du service compromis"
                      },
                      "breach_date": {
                        "type": "string",
                        "format": "date",
                        "description": "Date à laquelle la violation s'est produite"
                      },
                      "description": {
                        "type": "string",
                        "description": "Description de l'infraction"
                      },
                      "is_verified": {
                        "type": "boolean",
                        "description": "Indique si la fuite est vérifiée"
                      },
                      "data_classes": {
                        "type": "array",
                        "description": "Types de données exposées lors de la violation",
                        "items": {
                          "type": "string"
                        }
                      },
                      "breach_emails_count": {
                        "type": "integer",
                        "description": "Nombre d'adresses e-mail affectées par la violation de données"
                      }
                    }
                  }
                },
                "is_disposable": {
                  "type": "boolean",
                  "description": "Indique si l'e-mail provient d'un fournisseur jetable"
                },
                "is_undeliverable": {
                  "type": "boolean",
                  "description": "Indique si l'adresse e-mail n'est pas distribuable"
                },
                "verification_attempts": {
                  "type": "integer",
                  "description": "Nombre de tentatives de vérification pour cet e-mail"
                },
                "verified_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Horodatage de la vérification de l'e-mail"
                },
                "warnings": {
                  "type": "array",
                  "description": "Liste des avertissements liés à la vérification de l'e-mail",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "log_type": {
                        "type": "string"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                      }
                    }
                  }
                },
                "lifecycle": {
                  "type": "array",
                  "description": "Liste chronologique des événements du cycle de vie de la vérification d'e-mail.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string"
                      },
                      "timestamp": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "details": {
                        "type": "object",
                        "nullable": true,
                        "description": "Payload spécifique à l'événement. Les événements d'envoi contiennent `status`, `reason` ; les événements de vérification de code contiennent `code_tried`, `status` ; les événements d'état final contiennent `reason` — ou `null` lorsqu'il n'y a aucune raison à signaler (par ex. `EMAIL_VERIFICATION_APPROVED`).",
                        "properties": {
                          "status": {
                            "type": "string"
                          },
                          "reason": {
                            "type": "string",
                            "nullable": true
                          },
                          "code_tried": {
                            "type": "string"
                          }
                        }
                      },
                      "fee": {
                        "type": "number"
                      }
                    }
                  }
                },
                "matches": {
                  "type": "array",
                  "description": "Correspondances trouvées pour cette adresse e-mail. Chaque correspondance a une `source` : `session` (une autre session de vérification dans votre application correspondait au même e-mail, renvoyée avec `session_id`/`session_number`/`vendor_data`/`verification_date`) ou `list_entry` (l'e-mail figure sur une liste d'autorisation/de blocage gérée par l'organisation — voir `/management-api/lists/overview`). Les correspondances inter-sessions utilisent des `vendor_data` différents et sont plafonnées à 5.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "session_id": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                      },
                      "session_number": {
                        "type": "integer",
                        "nullable": true
                      },
                      "vendor_data": {
                        "type": "string",
                        "nullable": true
                      },
                      "verification_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                      },
                      "email": {
                        "type": "string",
                        "format": "email"
                      },
                      "status": {
                        "type": "string",
                        "nullable": true
                      },
                      "is_blocklisted": {
                        "type": "boolean"
                      },
                      "api_service": {
                        "type": "string",
                        "nullable": true
                      },
                      "source": {
                        "type": "string",
                        "enum": [
                          "session",
                          "list_entry"
                        ],
                        "description": "Origine de cette correspondance. `session` indique qu'une autre session de vérification dans votre application correspondait à cette valeur. `list_entry` indique que la valeur correspondait à une liste gérée par l'organisation (liste d'autorisation/liste de blocage) — consultez la vue d'ensemble des listes de l'API de gestion sur `/management-api/lists/overview` pour savoir comment gérer ces listes."
                      }
                    }
                  }
                },
                "email_intelligence": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/EmailIntelligence"
                    }
                  ],
                  "description": "Signaux d'analyse de l'e-mail. Présent uniquement lorsque le module complémentaire d'analyse de l'e-mail a été exécuté pour cette adresse."
                },
                "email_social": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/EmailSocialFootprint"
                    }
                  ],
                  "description": "Empreinte sociale de l'adresse. Présent uniquement lorsque le module complémentaire d'empreinte sociale a été exécuté pour cette adresse."
                }
              }
            }
          },
          "poa_verifications": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de Justificatif de domicile (POA)** — toujours un tableau JSON, jamais un objet `poa` singulier. `null` jusqu'à ce qu'au moins une étape POA ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, le `status` au niveau de la fonctionnalité, l'URL du fichier du document, l'émetteur, les dates, l'adresse analysée et `warnings[]`.",
            "items": {
              "type": "object",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "Identifiant unique de cette étape Justificatif de domicile (POA) dans le graphe du workflow."
                },
                "status": {
                  "type": "string",
                  "description": "Statut au niveau de la fonctionnalité de cette étape de justificatif de domicile. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`.",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Resub Requested"
                  ]
                },
                "document_file": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL du justificatif de domicile"
                },
                "issuing_state": {
                  "type": "string",
                  "description": "Code pays à deux lettres de l'État émetteur"
                },
                "document_type": {
                  "type": "string",
                  "description": "Type de justificatif de domicile"
                },
                "document_subtype": {
                  "type": "string",
                  "nullable": true,
                  "description": "Classification plus spécifique du document POA au sein de son `document_type`, lorsqu'une classification a été détectée. `null` dans le cas contraire."
                },
                "document_language": {
                  "type": "string",
                  "description": "Code de langue du document"
                },
                "document_metadata": {
                  "type": "object",
                  "properties": {
                    "file_size": {
                      "type": "integer",
                      "description": "Taille du document"
                    },
                    "content_type": {
                      "type": "string",
                      "description": "Type de contenu du document"
                    },
                    "creation_date": {
                      "type": "string",
                      "format": "date",
                      "description": "Date à laquelle le document a été créé"
                    },
                    "modified_date": {
                      "type": "string",
                      "format": "date",
                      "description": "Date à laquelle le document a été modifié"
                    },
                    "overlay_manipulation": {
                      "type": "object",
                      "nullable": true,
                      "description": "Analyse forensique de PDF pour suspicion de manipulation de texte superposé. Null lorsqu'aucune preuve de manipulation de superposition n'a été trouvée ou que le document n'était pas un PDF.",
                      "properties": {
                        "detected": {
                          "type": "boolean",
                          "description": "Indique si des preuves de manipulation de texte en superposition ont été détectées."
                        },
                        "analyzed": {
                          "type": "boolean",
                          "description": "Indique si le PDF a pu être analysé."
                        },
                        "analysis_incomplete": {
                          "type": "boolean",
                          "description": "Présent et vrai uniquement lorsque le fichier n'a pas pu être vérifié en totalité. Ce qui a été vérifié conserve ses constats lorsque c'est possible, et le document affiche l'avertissement de remplacement de texte non prouvé."
                        },
                        "signals": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Signaux d'analyse forensique qui se sont déclenchés, tels que duplicate_font_subset ou glyph_fragmentation."
                        },
                        "manipulated_regions": {
                          "type": "array",
                          "description": "Zones suspectées de manipulation selon les coordonnées de la page PDF.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "page": {
                                "type": "integer"
                              },
                              "x": {
                                "type": "number"
                              },
                              "y": {
                                "type": "number"
                              },
                              "width": {
                                "type": "number"
                              },
                              "height": {
                                "type": "number"
                              },
                              "page_width": {
                                "type": "number"
                              },
                              "page_height": {
                                "type": "number"
                              }
                            }
                          }
                        }
                      }
                    },
                    "creator": {
                      "type": "string",
                      "nullable": true,
                      "description": "Application de création enregistrée dans les métadonnées du document."
                    },
                    "producer": {
                      "type": "string",
                      "nullable": true,
                      "description": "Logiciel producteur enregistré dans les métadonnées du PDF."
                    },
                    "software": {
                      "type": "string",
                      "nullable": true,
                      "description": "Logiciel d'édition/de traitement enregistré dans les métadonnées du fichier."
                    },
                    "encryption": {
                      "type": "string",
                      "nullable": true,
                      "description": "Schéma de chiffrement du document, lorsqu'il est chiffré."
                    },
                    "is_signed": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "Indique si le PDF comporte une signature numérique."
                    },
                    "is_tampered": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "Indique si la validation de la signature indique que le fichier a été modifié après la signature."
                    },
                    "signature_info": {
                      "type": "object",
                      "nullable": true,
                      "description": "Détails de la ou des signatures numériques, le cas échéant."
                    },
                    "exif_original_date": {
                      "type": "string",
                      "nullable": true,
                      "description": "Date de capture originale EXIF, pour les téléversements d'images."
                    },
                    "exif_digitized_date": {
                      "type": "string",
                      "nullable": true,
                      "description": "Date de numérisation EXIF, pour les téléversements d'images."
                    },
                    "processed_by_known_editor": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "Indique si les métadonnées du fichier signalent un traitement par un éditeur de documents connu."
                    },
                    "has_different_creation_mod_date": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "Indique si les dates de création et de modification diffèrent — un signal fréquent de manipulation."
                    }
                  },
                  "description": "Métadonnées d'analyse médico-légale de fichier extraites du justificatif de domicile téléversé. Contient toujours les clés ci-dessous (les valeurs sont `null` lorsqu'elles ne s'appliquent pas, par exemple les dates EXIF pour les PDF). `null` si aucune métadonnée n'a pu être extraite.",
                  "nullable": true
                },
                "issuer": {
                  "type": "string",
                  "description": "Nom de l'émetteur du document"
                },
                "issue_date": {
                  "type": "string",
                  "format": "date",
                  "description": "Date à laquelle le document a été délivré"
                },
                "expiration_date": {
                  "type": "string",
                  "format": "date",
                  "nullable": true,
                  "description": "Date d'expiration du document, si disponible"
                },
                "poa_address": {
                  "type": "string",
                  "description": "Adresse brute issue du justificatif de domicile"
                },
                "poa_formatted_address": {
                  "type": "string",
                  "description": "Adresse formatée issue du document de justificatif de domicile"
                },
                "poa_parsed_address": {
                  "type": "object",
                  "properties": {
                    "address_type": {
                      "type": "string",
                      "description": "Type d'adresse (rue, avenue, etc.)"
                    },
                    "street_1": {
                      "type": "string",
                      "description": "Adresse postale principale"
                    },
                    "street_2": {
                      "type": "string",
                      "nullable": true,
                      "description": "Adresse de rue secondaire"
                    },
                    "city": {
                      "type": "string",
                      "description": "Nom de la ville"
                    },
                    "region": {
                      "type": "string",
                      "description": "Nom de la région ou de l'État"
                    },
                    "country": {
                      "type": "string",
                      "description": "Code pays à deux lettres"
                    },
                    "postal_code": {
                      "type": "string",
                      "description": "Code postal"
                    },
                    "document_location": {
                      "type": "object",
                      "properties": {
                        "latitude": {
                          "type": "number",
                          "description": "Coordonnée de latitude"
                        },
                        "longitude": {
                          "type": "number",
                          "description": "Coordonnée de longitude"
                        }
                      }
                    }
                  }
                },
                "name_on_document": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom du titulaire du compte / destinataire extrait du document de justificatif de domicile, utilisé pour la correspondance des noms. `null` lorsqu'aucun nom n'a pu être extrait."
                },
                "name_match_score_expected_details": {
                  "type": "number",
                  "nullable": true,
                  "description": "Score de similarité (0-100) entre `name_on_document` et le nom attendu fourni lors de la création de la session. `null` si l'un des côtés est manquant."
                },
                "name_match_score_id_verification": {
                  "type": "number",
                  "nullable": true,
                  "description": "Score de similarité (0-100) entre `name_on_document` et le nom extrait par l'étape de vérification d'identité. `null` si l'un des côtés est manquant."
                },
                "expected_details_address": {
                  "type": "string",
                  "nullable": true,
                  "description": "Adresse brute attendue pour la vérification"
                },
                "expected_details_formatted_address": {
                  "type": "string",
                  "nullable": true,
                  "description": "Adresse formatée attendue pour la vérification"
                },
                "expected_details_parsed_address": {
                  "type": "object",
                  "description": "Détails de l'adresse analysée attendus pour la vérification"
                },
                "extra_fields": {
                  "type": "object",
                  "description": "Coordonnées bancaires et de contact supplémentaires extraites du document.",
                  "properties": {
                    "bank_account_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "bank_iban": {
                      "type": "string",
                      "nullable": true
                    },
                    "bank_sort_code": {
                      "type": "string",
                      "nullable": true
                    },
                    "bank_routing_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "bank_swift_bic": {
                      "type": "string",
                      "nullable": true
                    },
                    "bank_branch_name": {
                      "type": "string",
                      "nullable": true
                    },
                    "bank_branch_address": {
                      "type": "string",
                      "nullable": true
                    },
                    "document_phone_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "additional_names": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "extra_files": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uri"
                  },
                  "description": "Fichiers supplémentaires de justificatif de domicile"
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "log_type": {
                        "type": "string"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                      }
                    }
                  }
                },
                "detected_codes": {
                  "type": "array",
                  "description": "Codes QR et codes-barres détectés sur chaque page traitée du document. Vide si aucun n'est trouvé. Un code QR localisé mais indécodable a `parsed_payload: null`.",
                  "items": {
                    "$ref": "#/components/schemas/DocumentAIDetectedCode"
                  }
                },
                "address_validation": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/AddressValidationResult"
                    }
                  ],
                  "nullable": true,
                  "description": "Validation de l'adresse figurant sur ce justificatif de domicile : indique si elle existe et sa forme normalisée, telle que lue sur le document (une correction ultérieure de `poa_address` ne relance pas la validation). Présent lorsque cette étape de justificatif de domicile a activé le module complémentaire Validation d'adresse et que le fichier téléversé a passé les contrôles du document ; `null` dans le cas contraire."
                }
              }
            }
          },
          "document_ai_documents": {
            "type": "array",
            "nullable": true,
            "description": "**Rapports Document AI regroupés par nœud de workflow** — toujours un tableau JSON, jamais un objet unique. `null` jusqu'à ce qu'au moins une étape Document AI ait produit des données. Présents uniquement lorsque `session_kind = user`. Chaque élément est un groupe de nœuds avec un `status` global, le `node_id`, un tableau `items[]` des résultats par document (données extraites indexées par la clé de champ configurée), et `warnings`.",
            "items": {
              "type": "object",
              "description": "Résultats de Document AI regroupés par nœud de workflow.",
              "properties": {
                "status": {
                  "type": "string",
                  "description": "Statut Document AI agrégé pour ce nœud, consolidé à partir de ses `items[]`.",
                  "enum": [
                    "Approved",
                    "Declined",
                    "In Review",
                    "Not Finished"
                  ]
                },
                "node_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identifiant unique de cette étape Document AI dans le graphe du workflow."
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "uuid": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "node_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "Nœud du graphe de workflow ayant produit ce document."
                      },
                      "document_key": {
                        "type": "string",
                        "description": "Clé du document configuré dans Document AI auquel ce fichier correspond."
                      },
                      "original_filename": {
                        "type": "string",
                        "nullable": true,
                        "description": "Nom de fichier tel que téléversé par l'utilisateur."
                      },
                      "file_size": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Taille du fichier en octets."
                      },
                      "file_url": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true,
                        "description": "Lien pré-signé de courte durée vers le fichier téléversé."
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "Approved",
                          "Declined",
                          "In Review",
                          "Not Finished"
                        ],
                        "description": "Statut Document AI par document."
                      },
                      "extracted_data": {
                        "type": "object",
                        "additionalProperties": true,
                        "nullable": true,
                        "description": "Valeurs extraites par Document AI, indexées par la `key` de champ configurée. Chaque valeur est une chaîne, un nombre ou `null`."
                      },
                      "detected_codes": {
                        "type": "array",
                        "description": "Codes QR et codes-barres détectés sur chaque page traitée. Vide si aucun n'est trouvé. Un code QR localisé mais indécodable a `parsed_payload: null`.",
                        "items": {
                          "$ref": "#/components/schemas/DocumentAIDetectedCode"
                        }
                      },
                      "fields": {
                        "type": "array",
                        "description": "Les champs d'extraction configurés pour ce document.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "key": {
                              "type": "string",
                              "description": "Clé de champ stable utilisée comme clé dans `extracted_data`."
                            },
                            "name": {
                              "type": "string",
                              "description": "Nom de champ lisible par l'humain."
                            },
                            "instruction": {
                              "type": "string",
                              "description": "Instruction d'extraction présentée au modèle."
                            },
                            "type": {
                              "type": "string",
                              "enum": [
                                "text",
                                "number",
                                "date"
                              ],
                              "description": "Type de valeur attendu du champ extrait."
                            },
                            "required": {
                              "type": "boolean",
                              "description": "Whether this field is required."
                            }
                          }
                        }
                      },
                      "document_metadata": {
                        "type": "object",
                        "nullable": true,
                        "description": "Métadonnées d'analyse médico-légale de fichier extraites du document téléversé (par ex. `is_tampered`). `null` si rien n'a pu être extrait."
                      },
                      "cross_check_result": {
                        "type": "object",
                        "nullable": true,
                        "description": "Recoupement des champs extraits du document avec d'autres données de la session. `null` lorsqu'aucun recoupement n'a été effectué."
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    }
                  }
                },
                "warnings": {
                  "type": "array",
                  "nullable": true,
                  "items": {
                    "type": "object"
                  },
                  "description": "Journaux d'avertissement générés pour ce nœud Document AI."
                }
              }
            }
          },
          "questionnaire_responses": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de réponses aux questionnaires** — toujours un tableau JSON, jamais un objet `questionnaire` singulier. `null` jusqu'à ce qu'au moins une étape de questionnaire ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, les métadonnées du questionnaire, les sections avec les éléments de formulaire et les réponses de l'utilisateur.",
            "items": {
              "type": "object",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "Identifiant unique de cette étape de questionnaire dans le graphe de workflow."
                },
                "questionnaire_id": {
                  "type": "string",
                  "description": "Identifiant unique du questionnaire"
                },
                "title": {
                  "type": "string",
                  "description": "Titre du questionnaire"
                },
                "description": {
                  "type": "string",
                  "description": "Description du questionnaire"
                },
                "languages": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Langues prises en charge"
                },
                "default_language": {
                  "type": "string",
                  "description": "Langue par défaut"
                },
                "is_active": {
                  "type": "boolean",
                  "description": "Indique si le questionnaire est actif"
                },
                "is_simple_questionnaire": {
                  "type": "boolean",
                  "description": "Indique si le questionnaire est un formulaire linéaire simple (sans graphe avec embranchements)."
                },
                "questionnaire_group_id": {
                  "type": "string",
                  "format": "uuid",
                  "nullable": true,
                  "description": "Identifiant stable du groupe de questionnaires pour toutes les versions."
                },
                "version": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Numéro de version du questionnaire auquel il a été répondu."
                },
                "published_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true,
                  "description": "Horodatage auquel cette version du questionnaire a été publiée."
                },
                "sections": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "title": {
                        "type": "string",
                        "nullable": true,
                        "description": "Titre de la section"
                      },
                      "description": {
                        "type": "string",
                        "nullable": true,
                        "description": "Description de la section"
                      },
                      "items": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "uuid": {
                              "type": "string",
                              "description": "Identifiant unique de l'élément"
                            },
                            "value": {
                              "type": "string",
                              "nullable": true,
                              "description": "Identifiant stable de nœud de cet élément de formulaire dans le graphe du questionnaire."
                            },
                            "element_type": {
                              "type": "string",
                              "description": "Type de l'élément de questionnaire"
                            },
                            "is_required": {
                              "type": "boolean",
                              "description": "Indique si l'élément est obligatoire"
                            },
                            "title": {
                              "type": "string",
                              "description": "Titre de l'élément"
                            },
                            "description": {
                              "type": "string",
                              "nullable": true,
                              "description": "Description de l'élément"
                            },
                            "placeholder": {
                              "type": "string",
                              "nullable": true,
                              "description": "Texte indicatif"
                            },
                            "choices": {
                              "type": "array",
                              "nullable": true,
                              "items": {
                                "type": "object",
                                "properties": {
                                  "label": {
                                    "type": "string"
                                  },
                                  "value": {
                                    "type": "string"
                                  },
                                  "requires_text_input": {
                                    "type": "boolean",
                                    "description": "Indique si ce choix nécessite une saisie de texte supplémentaire",
                                    "nullable": true
                                  }
                                },
                                "required": [
                                  "label",
                                  "value"
                                ]
                              },
                              "description": "Choix pour les éléments de liste déroulante ou à choix unique"
                            },
                            "max_files": {
                              "type": "integer",
                              "description": "Nombre maximal de fichiers autorisés",
                              "nullable": true
                            },
                            "answer": {
                              "type": "object",
                              "description": "Réponse fournie pour l'élément",
                              "properties": {
                                "value": {
                                  "type": "string",
                                  "nullable": true
                                },
                                "text": {
                                  "type": "string",
                                  "nullable": true
                                },
                                "files": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "nullable": true
                                }
                              }
                            },
                            "required_if": {
                              "type": "object",
                              "nullable": true,
                              "description": "Règle d'exigence conditionnelle, lorsque l'élément n'est requis que pour certaines réponses."
                            },
                            "repeatable_config": {
                              "type": "object",
                              "nullable": true,
                              "description": "Configuration pour les groupes d'éléments répétables, le cas échéant."
                            }
                          },
                          "required": [
                            "uuid",
                            "value",
                            "element_type",
                            "is_required",
                            "title"
                          ]
                        }
                      }
                    }
                  }
                },
                "status": {
                  "type": "string",
                  "description": "Statut du questionnaire"
                }
              }
            }
          },
          "bank_verifications": {
            "type": "array",
            "nullable": true,
            "description": "Résultats de la vérification bancaire, un élément par étape de vérification bancaire, pour la Vérification des utilisateurs et la Vérification d'entreprise (KYB). `null` jusqu'à ce qu'une étape en produise un. Le champ `method` de chaque élément indique comment le compte a été vérifié : `open_banking` (connexion bancaire) ou `account_lookup` (vérification de compte), ou une solution de repli `statement` ou `microdeposits`, et `none` lorsque la personne a continué sans banque avant qu'une tentative ne soit évaluée (`continued_without_bank`). Voir [Méthodes de vérification bancaire](/fr/core-technology/bank-verification/verification-methods).",
            "items": {
              "$ref": "#/components/schemas/BankVerificationResult"
            }
          },
          "signatures": {
            "type": "array",
            "description": "Résultats de la Signature électronique, un élément par signataire et par étape de signature, pour la Vérification des utilisateurs et la Vérification d'entreprise. Présent uniquement lorsque le workflow comprend une étape de Signature électronique ; tableau vide jusqu'à ce qu'un signataire l'atteigne. Voir le [rapport de Signature électronique](/fr/core-technology/electronic-signature/report-electronic-signature).",
            "items": {
              "$ref": "#/components/schemas/SignatureResult"
            }
          },
          "aml_screenings": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de filtrage AML** — toujours un tableau JSON, jamais un objet `aml` unique. `null` jusqu'à ce qu'au moins une étape AML ait produit des données. Chaque élément est le rapport complet, incluant `node_id`, le `status` au niveau de la fonctionnalité, `total_hits`, `entity_type`, `hits[]`, `score`, `screened_data`, `is_ongoing_monitoring_enabled` et `warnings[]`.",
            "items": {
              "$ref": "#/components/schemas/AMLScreening"
            }
          },
          "ip_analyses": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports d'Analyse de l'appareil et de l'IP** — toujours un tableau JSON, jamais un objet `ip_analysis` singulier. `null` jusqu'à ce qu'au moins une étape d'analyse IP ait produit des données. Chaque élément est le rapport complet, comprenant `node_id`, le `status` au niveau de la fonctionnalité, les données IP et de géolocalisation, l'empreinte de l'appareil et `warnings[]`. Les entrées présentant un doublon `(node_id, ip_address, device_fingerprint)` sont dédupliquées côté serveur.",
            "items": {
              "type": "object",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "Identifiant unique de cette étape d'Analyse de l'appareil et de l'IP dans le graphe du workflow."
                },
                "status": {
                  "type": "string",
                  "description": "Statut au niveau de la fonctionnalité de cette entrée d'Analyse de l'appareil et de l'IP. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`.",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Resub Requested"
                  ]
                },
                "device_brand": {
                  "type": "string",
                  "description": "Marque de l'appareil utilisé"
                },
                "device_model": {
                  "type": "string",
                  "description": "Modèle de l'appareil utilisé"
                },
                "browser_family": {
                  "type": "string",
                  "description": "Famille de navigateur utilisée"
                },
                "os_family": {
                  "type": "string",
                  "description": "Famille de système d'exploitation"
                },
                "platform": {
                  "type": "string",
                  "description": "Type de plateforme (mobile, desktop, etc.)"
                },
                "device_fingerprint": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identifiant unique de l'empreinte de l'appareil"
                },
                "ip_country": {
                  "type": "string",
                  "description": "Pays détecté à partir de l'IP"
                },
                "ip_country_code": {
                  "type": "string",
                  "description": "Code pays à deux lettres dérivé de l'IP"
                },
                "ip_state": {
                  "type": "string",
                  "description": "État/région détecté(e) à partir de l'IP"
                },
                "ip_city": {
                  "type": "string",
                  "description": "Ville détectée à partir de l'IP"
                },
                "latitude": {
                  "type": "number",
                  "description": "Coordonnée de latitude de la localisation de l'IP"
                },
                "longitude": {
                  "type": "number",
                  "description": "Coordonnée de longitude de la localisation IP"
                },
                "ip_address": {
                  "type": "string",
                  "description": "Adresse"
                },
                "isp": {
                  "type": "string",
                  "nullable": true,
                  "description": "Fournisseur d'accès à Internet"
                },
                "organization": {
                  "type": "string",
                  "nullable": true,
                  "description": "Organisation associée à l'IP"
                },
                "is_vpn_or_tor": {
                  "type": "boolean",
                  "description": "Indique si l'adresse provient d'un VPN ou du réseau Tor"
                },
                "is_data_center": {
                  "type": "boolean",
                  "description": "Indique si l'adresse provient d'un centre de données"
                },
                "time_zone": {
                  "type": "string",
                  "description": "Fuseau horaire détecté à partir de l'IP"
                },
                "time_zone_offset": {
                  "type": "string",
                  "description": "Décalage du fuseau horaire"
                },
                "ip": {
                  "type": "object",
                  "description": "Géolocalisation IP de cette entrée ainsi que les distances orthodromiques (km) jusqu'à l'adresse du document d'identité et l'adresse du justificatif de domicile. Les distances sont `null` lorsque l'un des deux côtés ne dispose pas d'une localisation exploitable.",
                  "properties": {
                    "location": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "latitude": {
                          "type": "number",
                          "example": 41.2706327
                        },
                        "longitude": {
                          "type": "number",
                          "example": 1.9770097
                        }
                      },
                      "description": "Coordonnées, ou `null` si non disponibles."
                    },
                    "distance_from_id_document": {
                      "type": "number",
                      "nullable": true,
                      "example": 23.4
                    },
                    "distance_from_poa_document": {
                      "type": "number",
                      "nullable": true,
                      "example": 12.3
                    }
                  }
                },
                "id_document": {
                  "type": "object",
                  "description": "Localisation extraite de l'adresse du document d'identité plus les distances (km) jusqu'à la géolocalisation IP et l'adresse du document de justificatif de domicile (POA). `location` est `null` lorsqu'aucune adresse de document n'a pu être géocodée.",
                  "properties": {
                    "location": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "latitude": {
                          "type": "number",
                          "example": 41.2706327
                        },
                        "longitude": {
                          "type": "number",
                          "example": 1.9770097
                        }
                      },
                      "description": "Coordonnées, ou `null` si non disponibles."
                    },
                    "distance_from_ip": {
                      "type": "number",
                      "nullable": true,
                      "example": 23.4
                    },
                    "distance_from_poa_document": {
                      "type": "number",
                      "nullable": true,
                      "example": 18.7
                    }
                  }
                },
                "poa_document": {
                  "type": "object",
                  "description": "Localisation extraite du justificatif de domicile plus les distances (km) jusqu'à la géolocalisation IP et l'adresse du document d'identité. `location` est `null` lorsque la session ne comporte pas d'étape POA ou que l'adresse n'a pas pu être géocodée.",
                  "properties": {
                    "location": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "latitude": {
                          "type": "number",
                          "example": 41.2706327
                        },
                        "longitude": {
                          "type": "number",
                          "example": 1.9770097
                        }
                      },
                      "description": "Coordonnées, ou `null` si non disponibles."
                    },
                    "distance_from_ip": {
                      "type": "number",
                      "nullable": true,
                      "example": 12.3
                    },
                    "distance_from_id_document": {
                      "type": "number",
                      "nullable": true,
                      "example": 18.7
                    }
                  }
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "log_type": {
                        "type": "string"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                      }
                    }
                  }
                },
                "matches": {
                  "type": "array",
                  "description": "Correspondances inter-sessions trouvées pour l'adresse IP ou l'identité de l'appareil de cette entrée. Chaque correspondance est une autre session de vérification dans votre application (`source` est toujours `session`) qui partage la même valeur, appartenant toujours à un utilisateur du fournisseur / `vendor_data` différent de la session actuelle, plafonnée à 5 par collecteur (`device_fingerprint` additionne deux collecteurs plafonnés indépendamment, jusqu'à 10 entrées sont donc possibles). Chaque élément comporte `match_source`, `confidence`, `match_mode`, `device_info` et `location_info` ; les clés `recovery_similarity`, `tls_ja4_corroborated` et `recovery_gate_reason` ne sont présentes que lorsque `match_source` est `recovered_high`.",
                  "items": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "session_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "ID de session de la session correspondante."
                      },
                      "session_number": {
                        "type": "integer",
                        "description": "Numéro séquentiel de la session correspondante."
                      },
                      "vendor_data": {
                        "type": "string",
                        "nullable": true,
                        "description": "`vendor_data` de la session correspondante — toujours différent de l'utilisateur du fournisseur de la session actuelle."
                      },
                      "verification_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Date de création de la session correspondante (`YYYY-MM-DDTHH:MM:SSZ`)."
                      },
                      "match_type": {
                        "type": "string",
                        "enum": [
                          "ip_address",
                          "device_fingerprint"
                        ],
                        "description": "Indique si la correspondance portait sur l'adresse IP ou sur l'empreinte de l'appareil"
                      },
                      "match_source": {
                        "type": "string",
                        "enum": [
                          "ip_address",
                          "persistent_id",
                          "legacy_fp",
                          "recovered_high"
                        ],
                        "description": "Manière dont cette correspondance a été établie : `ip_address` (adresse partagée — colocalisation réseau, et non une revendication d'identité d'appareil), `persistent_id` (identifiant persistant d'appareil stocké exact), `legacy_fp` (hachage d'empreinte d'appareil `didit-fp-*` hérité) ou `recovered_high` (résultat de récupération d'empreinte approximative à haute confiance). Les candidats de récupération à plus faible confiance apparaissent uniquement sous forme d'avertissements de risque, jamais dans ce tableau."
                      },
                      "matched_value": {
                        "type": "string",
                        "nullable": true,
                        "description": "La valeur correspondante : l'adresse IP partagée, l'identifiant persistant de l'appareil ou le hash d'empreinte historique, ou — pour `recovered_high` — l'UUID de l'appareil récupéré."
                      },
                      "status": {
                        "type": "string",
                        "description": "Statut de cycle de vie de la session correspondante."
                      },
                      "is_blocklisted": {
                        "type": "boolean",
                        "description": "Indique si la valeur correspondante figure sur une liste de blocage. Actuellement toujours `false` pour les correspondances d'appareil/IP."
                      },
                      "api_service": {
                        "type": "string",
                        "nullable": true,
                        "description": "Service d'API autonome de la session correspondante ; `null` pour les sessions de workflow."
                      },
                      "source": {
                        "type": "string",
                        "enum": [
                          "session"
                        ],
                        "description": "Toujours `session` pour les correspondances d'appareil/IP — chaque correspondance est une autre session de vérification dans votre application."
                      },
                      "device_info": {
                        "type": "object",
                        "description": "Détails de l'appareil observés sur la session correspondante.",
                        "properties": {
                          "device_brand": {
                            "type": "string",
                            "nullable": true
                          },
                          "device_model": {
                            "type": "string",
                            "nullable": true
                          },
                          "browser_family": {
                            "type": "string",
                            "nullable": true
                          },
                          "os_family": {
                            "type": "string",
                            "nullable": true
                          },
                          "platform": {
                            "type": "string",
                            "nullable": true
                          },
                          "device_fingerprint": {
                            "type": "string",
                            "nullable": true
                          }
                        }
                      },
                      "location_info": {
                        "type": "object",
                        "description": "Détails du réseau et de la géolocalisation observés sur la session correspondante.",
                        "properties": {
                          "ip_address": {
                            "type": "string",
                            "nullable": true
                          },
                          "ip_country": {
                            "type": "string",
                            "nullable": true
                          },
                          "ip_country_code": {
                            "type": "string",
                            "nullable": true
                          },
                          "ip_state": {
                            "type": "string",
                            "nullable": true
                          },
                          "ip_city": {
                            "type": "string",
                            "nullable": true
                          },
                          "is_vpn_or_tor": {
                            "type": "boolean"
                          },
                          "is_data_center": {
                            "type": "boolean"
                          }
                        }
                      },
                      "confidence": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1,
                        "description": "Confiance de l'identification côté serveur, calculée comme `1 - P(false positive)` : `1.0` pour les correspondances déterministes (`persistent_id` ou `recovered_high` ancré au matériel), `0.5` pour `legacy_fp`, `0.0` pour `ip_address` (colocalisation uniquement), et une valeur ajustée par corroboration inférieure à `1.0` pour les correspondances probabilistes récupérées (plus élevée lorsque l'empreinte TLS JA4 et le pays de l'IP concordent de manière indépendante)."
                      },
                      "match_mode": {
                        "type": "string",
                        "enum": [
                          "deterministic",
                          "probabilistic",
                          "co_occurrence"
                        ],
                        "description": "Classe de preuve de la correspondance : `deterministic` (identifiant exact stocké ou ancré matériellement, qui ne peut pas entrer en collision entre appareils physiques), `probabilistic` (preuve fondée sur une empreinte approximative) ou `co_occurrence` (réseau partagé uniquement, aucune revendication d'identité d'appareil)."
                      },
                      "recovery_similarity": {
                        "type": "number",
                        "description": "Similarité cosinus de la correspondance de récupération d'empreinte, arrondie à 4 décimales. Présent uniquement lorsque `match_source` est `recovered_high`."
                      },
                      "tls_ja4_corroborated": {
                        "type": "boolean",
                        "description": "Indique si les empreintes TLS JA4 des deux observations concordent — un signal observé côté serveur que le navigateur ne peut pas usurper. Présent uniquement lorsque `match_source` vaut `recovered_high`."
                      },
                      "recovery_gate_reason": {
                        "type": "string",
                        "description": "Raison pour laquelle la correspondance de récupération a franchi le filtre strict des faux positifs : `hardware_root_match` (un identifiant d'appareil ancré au matériel correspondait exactement) ou, sur les configurations qui admettent des preuves basées uniquement sur des sondes, `exact_composite_plus_<n>_families` / `very_high_similarity_plus_<n>_families`. Présent uniquement lorsque `match_source` est `recovered_high`."
                      }
                    }
                  }
                },
                "browser_version": {
                  "type": "string",
                  "nullable": true
                },
                "os_version": {
                  "type": "string",
                  "nullable": true
                },
                "user_agent": {
                  "type": "string",
                  "nullable": true,
                  "description": "La chaîne de l'agent utilisateur du navigateur."
                },
                "accept_language": {
                  "type": "string",
                  "nullable": true,
                  "description": "L'en-tête `Accept-Language` envoyé par le navigateur."
                },
                "session_identifier": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identifiant de la session de navigation dans laquelle la vérification s'est déroulée."
                },
                "session_age_ms": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Âge de cette session de navigation en millisecondes lors de l'exécution de l'étape."
                },
                "coords_accuracy": {
                  "type": "number",
                  "nullable": true,
                  "description": "Rayon de précision, en mètres, des coordonnées signalées par l'appareil."
                },
                "raw_device_data": {
                  "type": "object",
                  "nullable": true,
                  "additionalProperties": true,
                  "description": "Signaux bruts de l'appareil collectés pour l'étape."
                }
              }
            }
          },
          "geolocation_checks": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de résultats de vérification de localisation**, un par étape de vérification de localisation : la tentative acceptée de cette étape. `null` jusqu'à ce qu'une étape de vérification de localisation ait produit des données. Les tentatives antérieures de la même étape se trouvent dans `geolocation_attempts`.",
            "items": {
              "$ref": "#/components/schemas/GeolocationCheck"
            }
          },
          "geolocation_attempts": {
            "type": "array",
            "nullable": true,
            "description": "Chaque tentative de chaque étape de vérification de localisation de cette session, de la plus ancienne à la plus récente. Les tentatives remplacées par une nouvelle soumission sont exclues. Un workflow qui masque `geolocation_checks` via ses attributs de réponse masque également cette liste.",
            "items": {
              "$ref": "#/components/schemas/GeolocationAttempt"
            }
          },
          "database_validations": {
            "type": "array",
            "nullable": true,
            "description": "**Tableau de rapports de Validation en base de données** — toujours un tableau JSON, jamais un objet `database_validation` singulier. `null` jusqu'à ce qu'au moins une étape de validation en base de données ait produit des données. Chaque élément correspond au rapport complet, incluant `node_id`, le `status` au niveau de la fonctionnalité, `screened_data`, les `validations[]` par service (chacune avec son `source_data` de registre) et `warnings[]`. Les champs `screened_data` et `source_data` varient selon le pays :\n\n**ARG (Argentine)** : screened_data : {document_number, selfie, gender, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name, date_of_birth, date_of_death, tax_id, tax_id_type, face_match_score, sit_1_since, banks, last_position, highest_position, rejected_checks}. Utilise la validation biométrique par correspondance faciale de RENAPER. Le genre est automatiquement déduit de l'analyse du visage ou du prénom lorsqu'il n'est pas présent sur le document (ex. permis de conduire)\n\n**BOL (Bolivie)** : screened_data : {document_number, date_of_birth, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name, date_of_birth, gender}\n\n**BRA (Brésil)** : screened_data : {tax_number, first_name, last_name, date_of_birth}. source_data inclut toujours {identification_number, first_name, last_name, date_of_birth, lgpd_minor, minor_under_18, minor_under_16} pour les correspondances CPF réussies. Les recherches réussies pour les adultes définissent ces indicateurs à false. Le service Consulta CPF de la Receita Federal peut renvoyer HTTP 422 (mineur de moins de 18 ans) ou 451 (moins de 16 ans) avec des données retenues en vertu de la LGPD ; dans ces cas, source_data définit les indicateurs de minorité à true selon le cas, inclut le statut HTTP en amont, et la validation au niveau du champ est no_match. Consultez la section Brésil de la référence des codes de résultat de la Validation en base de données pour la liste complète des codes.\n\n**CHL (Chili)** : screened_data : {personal_number, first_name, last_name, date_of_birth}. source_data : {identification_number, first_name, last_name, date_of_birth, gender}\n\n**COL (Colombie)** : screened_data : {document_number, document_type, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name, date_of_birth, document_type}\n\n**CRI (Costa Rica)** : screened_data : {personal_number, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name}\n\n**DOM (République dominicaine)** : screened_data : {personal_number}. source_data : {identification_number} (renvoie valid/invalid uniquement)\n\n**ECU (Équateur)** : screened_data : {personal_number, first_name, last_name}. source_data : {identification_number, first_name, last_name, street, formatted_address, gender, nationality, education, marital_status, spouse, mother_name, father_name, profession}\n\n**ESP (Espagne)** : screened_data : {personal_number, document_type, expiration_date, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name, document_type, expiration_date}\n\n**GTM (Guatemala)** : screened_data : {document_number, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name}\n\n**HND (Honduras)** : screened_data : {document_number, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name}\n\n**MEX (Mexique)** : screened_data : {personal_number (CURP), first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name, date_of_birth, gender, nationality, curp_status, state_of_birth, doc_probatorio, registration_year, registration_state, registration_municipality, num_acta, crip, issuing_state_code, foreign_registry_number, folio_carta, folio_certificado}. Utilise le registre d'état civil RENAPO. Un service distinct de vérification de validité INE est également disponible pour MEX en tant que validation supplémentaire individuelle.\n\n**PAN (Panama)** : screened_data : {personal_number, selfie}. source_data : {identification_number}. Utilise la validation biométrique SIB\n\n**PER (Pérou)** : screened_data : {personal_number (DNI), first_name, last_name}. source_data : {identification_number, first_name, last_name, paternal_name, maternal_name, verification_number, verification_letter}\n\n**PRY (Paraguay)** : screened_data : {document_number, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name}\n\n**SLV (Salvador)** : screened_data : {document_number, date_of_birth, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name}\n\n**URY (Uruguay)** : screened_data : {personal_number, date_of_birth, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name}\n\n**VEN (Venezuela)** : screened_data : {document_number, first_name, last_name}. source_data : {identification_number, first_name, last_name, full_name, gender, date_of_birth, document_type}",
            "items": {
              "type": "object",
              "properties": {
                "node_id": {
                  "type": "string",
                  "description": "Identifiant unique de cette étape de validation en base de données dans le graphe de workflow."
                },
                "issuing_state": {
                  "type": "string",
                  "description": "Code ISO 3166-1 alpha-3 du pays dont les sources gouvernementales ou de registres ont été interrogées (par ex. `BRA`, `MEX`, `ESP`, `NGA`, `IDN`). La Validation en base de données couvre 60+ pays à travers les Amériques, l'Europe, l'Afrique, le Moyen-Orient et l'Asie-Pacifique, ainsi que des sources mondiales multi-pays — la couverture s'élargit régulièrement, considérez donc cette valeur comme un ensemble ouvert plutôt qu'un enum fixe."
                },
                "validation_type": {
                  "type": "string",
                  "enum": [
                    "one_by_one",
                    "two_by_two",
                    "not_enabled"
                  ],
                  "description": "Manière dont le résultat a été corroboré : `one_by_one` (résultat d'un service unique), `two_by_two` (au moins deux services distincts ont fait correspondre indépendamment et intégralement le numéro d'identification), ou `not_enabled` (conservé lorsqu'aucun service n'a produit de correspondance exploitable). La valeur n'est jamais `null`. Des modes de validation biométrique 2x2 dédiés sont actuellement disponibles pour `ECU` et `PER`."
                },
                "screened_data": {
                  "type": "object",
                  "description": "Les données d'entrée utilisées pour la validation. Les champs varient selon le pays — consultez la documentation de Validation en base de données (`/core-technology/database-validation/overview`) pour les formats spécifiques à chaque pays.",
                  "properties": {
                    "last_name": {
                      "type": "string"
                    },
                    "first_name": {
                      "type": "string"
                    },
                    "tax_number": {
                      "type": "string",
                      "description": "Brésil : CPF (11 chiffres)"
                    },
                    "personal_number": {
                      "type": "string",
                      "description": "Chili : RUT, DOM : Cédula (11 chiffres), ECU : Cédula (10 chiffres), ESP : DNI/NIE, MEX : CURP (18 car.), PER : DNI (8 chiffres), URY : CI"
                    },
                    "document_number": {
                      "type": "string",
                      "description": "ARG : DNI, BOL : CI, COL : Cédula, GTM : DPI, HND : DNI, PAN : Cédula, PRY : CI, SLV : DUI, VEN : Cédula"
                    },
                    "date_of_birth": {
                      "type": "string",
                      "format": "date"
                    },
                    "document_type": {
                      "type": "string",
                      "description": "COL : CC/CE/TI/NIT, ESP : ID/PASSPORT"
                    },
                    "expiration_date": {
                      "type": "string",
                      "format": "date",
                      "description": "Requis pour ESP"
                    }
                  }
                },
                "validations": {
                  "type": "array",
                  "description": "Une entrée par service de registre ayant retourné un payload de validation. Chaque entrée identifie le service (`service_id`, `service_name`) et contient la comparaison `validation` par champ, le `outcome_code` / `outcome_detail` du service lorsqu'ils sont communiqués, et l'enregistrement de registre normalisé dans `source_data`.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "service_id": {
                        "type": "string",
                        "description": "Identifiant du service de registre ayant produit ce résultat de validation.",
                        "example": "bra_cpf"
                      },
                      "service_name": {
                        "type": "string",
                        "description": "Nom lisible par l'humain du service de registre.",
                        "example": "Brazil - CPF status check"
                      },
                      "validation": {
                        "type": "object",
                        "description": "Les résultats des validations de champs.",
                        "properties": {
                          "full_name": {
                            "type": "string",
                            "description": "Résultat de correspondance pour le nom complet (par ex., 'full_match', 'partial_match', 'no_match')."
                          },
                          "date_of_birth": {
                            "type": "string",
                            "description": "Résultat de correspondance pour la date de naissance."
                          },
                          "identification_number": {
                            "type": "string",
                            "description": "Résultat de correspondance pour le numéro d'identification."
                          }
                        }
                      },
                      "outcome_code": {
                        "type": "string",
                        "nullable": true,
                        "description": "Résultat lisible par machine de la recherche au registre (par ex. `MATCH`, `NO_MATCH`, `PARTIAL_MATCH`, `INCONCLUSIVE`, codes spécifiques à la source). Présent lorsque le service en transmet un."
                      },
                      "outcome_detail": {
                        "type": "string",
                        "nullable": true,
                        "description": "Explication lisible par l'humain de `outcome_code`, lorsqu'elle est fournie par le service."
                      },
                      "source_data": {
                        "type": "object",
                        "description": "Les données renvoyées par la base de données gouvernementale. Champs communs : identification_number, first_name, last_name, full_name, date_of_birth, gender. Champs supplémentaires par pays : BRA inclut toujours lgpd_minor, minor_under_18 et minor_under_16 lors des correspondances CPF réussies ; il inclut également le statut HTTP en amont lorsque les données CPF sont retenues en vertu de la LGPD (HTTP 422/451). ECU ajoute street, formatted_address, nationality, education, marital_status, spouse, mother_name, father_name, profession. PER ajoute paternal_name, maternal_name, verification_number, verification_letter. ESP ajoute document_type, expiration_date. VEN/COL ajoutent document_type.",
                        "additionalProperties": true
                      }
                    }
                  }
                },
                "errors": {
                  "type": "array",
                  "description": "Erreurs renvoyées par les services de registre lors de la validation, chacune associée au `service_id` qui l'a produite. **Cette clé est entièrement omise lorsqu'il n'y a pas d'erreur.**",
                  "items": {
                    "type": "object",
                    "description": "L'objet d'erreur du service en amont propagé tel quel — ses clés varient selon le service (généralement un message/code et des détails spécifiques au fournisseur) — plus `service_id` identifiant le service en erreur.",
                    "properties": {
                      "service_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "Identifiant du service de registre ayant rencontré une erreur."
                      }
                    },
                    "additionalProperties": true
                  }
                },
                "match_type": {
                  "type": "string",
                  "enum": [
                    "no_match",
                    "partial_match",
                    "full_match"
                  ],
                  "nullable": true,
                  "description": "Le résultat global de correspondance parmi les services interrogés. `null` tant que la validation n'a pas été évaluée."
                },
                "status": {
                  "type": "string",
                  "description": "Statut au niveau de la fonctionnalité de cette validation en base de données. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`.",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Resub Requested"
                  ]
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feature": {
                        "type": "string",
                        "enum": [
                          "ID_VERIFICATION",
                          "NFC",
                          "LIVENESS",
                          "FACEMATCH",
                          "PROOF_OF_ADDRESS",
                          "PHONE",
                          "EMAIL",
                          "AML",
                          "LOCATION",
                          "DATABASE_VALIDATION",
                          "QUESTIONNAIRE",
                          "DOCUMENT_AI",
                          "KYB_REGISTRY",
                          "KYB_DOCUMENTS",
                          "KYB_KEY_PEOPLE",
                          "GEOLOCATION",
                          "SIGNATURE"
                        ],
                        "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                      },
                      "risk": {
                        "type": "string"
                      },
                      "additional_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "log_type": {
                        "type": "string"
                      },
                      "short_description": {
                        "type": "string"
                      },
                      "long_description": {
                        "type": "string"
                      },
                      "node_id": {
                        "type": "string",
                        "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                      }
                    }
                  },
                  "description": "Avertissements liés à la validation en base de données."
                }
              }
            }
          },
          "database_validation_not_performed_reason": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Raison pour laquelle une validation en base de données configurée n'a produit aucun résultat, sous la forme `{code, message}` plus des champs de contexte. Présent uniquement lorsque `database_validations` est `null` pour un workflow comportant cette étape, afin de pouvoir distinguer « le registre a validé » de « rien n'a été exécuté ». `null` dans le cas contraire.",
            "properties": {
              "code": {
                "type": "string",
                "description": "Raison stable lisible par machine."
              },
              "message": {
                "type": "string",
                "description": "Explication lisible par l'humain."
              }
            }
          },
          "reviews": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "user": {
                  "type": "string",
                  "description": "Qui a effectué l'examen. Généralement l'identifiant du réviseur dans la console (son e-mail), mais la valeur est `\"API Client\"` pour les mises à jour de statut effectuées avec une clé API et `\"Unknown\"` lorsqu'aucun acteur n'a pu être résolu — n'analysez donc pas ce champ comme une adresse e-mail."
                },
                "new_status": {
                  "type": "string"
                },
                "comment": {
                  "type": "string"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "assignee": {
            "type": "object",
            "nullable": true,
            "description": "Le réviseur de la Console auquel la session est assignée, ou `null` si personne ne la détient.",
            "properties": {
              "email": {
                "type": "string",
                "format": "email"
              },
              "assigned_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "waiting_since": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où la session a commencé à attendre un examen. `null` sauf si la session est `In Review` et que votre application définit un délai d'examen."
          },
          "sla_due_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date limite de l'examen. `null` sauf si la session est `In Review` et que votre application définit une date limite d'examen."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de création de la session (ISO 8601, UTC)."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage auquel l'expiration de cette session est planifiée. Défini sur les sessions de vérification des utilisateurs (KYC) lorsqu'une expiration a été configurée lors de la création (ou une fois que le statut `Approved` déclenche le calcul de l'expiration du KYC). `null` pour les sessions sans expiration configurée, et pour les types qui n'utilisent pas d'expiration (par ex. les sessions de vérification d'entreprise (KYB) qui n'ont jamais reçu d'`expires_at`)."
          },
          "registry_checks": {
            "type": "array",
            "nullable": true,
            "description": "Vérifications au registre des sociétés. Présent uniquement lorsque `session_kind = business`. Chaque élément encapsule le payload complet du registre des sociétés.",
            "items": {
              "type": "object",
              "description": "Une vérification de registre des sociétés — le payload complet du registre des sociétés enrichi avec la structure de l'actionnariat et les avertissements. Présent uniquement lorsque `session_kind = business`.",
              "properties": {
                "status": {
                  "type": "string",
                  "description": "Statut du cycle de vie de la fonctionnalité."
                },
                "node_id": {
                  "type": "string",
                  "nullable": true
                },
                "data_resolved": {
                  "type": "boolean"
                },
                "company": {
                  "type": "object",
                  "description": "Payload complet du registre pour l'entreprise (enregistrement du registre fusionné avec les données fournies par l'utilisateur ou modifiées dans la console).",
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "node_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "status": {
                      "type": "string"
                    },
                    "registry_status": {
                      "type": "string",
                      "nullable": true
                    },
                    "data_resolved": {
                      "type": "boolean"
                    },
                    "company_name": {
                      "type": "string"
                    },
                    "registration_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "country_code": {
                      "type": "string",
                      "description": "Pays de constitution (ISO 3166-1 alpha-2, par ex. `GB`, `DE`, `US`)."
                    },
                    "region": {
                      "type": "string",
                      "nullable": true,
                      "description": "Code de subdivision ISO 3166-2 le cas échéant (ex. `CA`, `NY` pour les États américains)."
                    },
                    "company_type": {
                      "type": "string",
                      "nullable": true
                    },
                    "incorporation_date": {
                      "type": "string",
                      "format": "date",
                      "nullable": true
                    },
                    "registered_address": {
                      "type": "string",
                      "nullable": true
                    },
                    "tax_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "risk_level": {
                      "type": "string",
                      "enum": [
                        "LOW",
                        "MEDIUM",
                        "HIGH"
                      ],
                      "nullable": true
                    },
                    "verification_status": {
                      "type": "string",
                      "nullable": true
                    },
                    "is_from_registry": {
                      "type": "boolean"
                    },
                    "fetch_status": {
                      "type": "string",
                      "nullable": true
                    },
                    "alternative_names": {
                      "type": "string",
                      "nullable": true,
                      "description": "Dénominations commerciales, alternatives, anciennes ou dans la langue d'origine de l'entreprise sous forme de texte, lorsqu'elles sont déclarées."
                    },
                    "nature_of_business": {
                      "type": "string",
                      "nullable": true
                    },
                    "registered_capital": {
                      "type": "string",
                      "nullable": true
                    },
                    "registered_capital_amount": {
                      "type": "string",
                      "format": "decimal",
                      "nullable": true,
                      "description": "Montant du capital social/enregistré sous forme de chaîne décimale (par ex. `\"100.00\"`), extrait du dépôt au registre. `null` lorsqu'il n'est pas disponible."
                    },
                    "registered_capital_currency": {
                      "type": "string",
                      "nullable": true,
                      "description": "Code de devise ISO 4217 de `registered_capital_amount` (ex. `\"GBP\"`). `null` lorsqu'il n'est pas disponible."
                    },
                    "website": {
                      "type": "string",
                      "nullable": true
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "nullable": true
                    },
                    "phone": {
                      "type": "string",
                      "nullable": true
                    },
                    "legal_entity_identifier": {
                      "type": "string",
                      "nullable": true
                    },
                    "location_of_registration": {
                      "type": "string",
                      "nullable": true
                    },
                    "vat_number": {
                      "type": "string",
                      "nullable": true,
                      "description": "Numéro de TVA de l'UE, lorsqu'il est recueilli lors de l'étape de registre hébergée ou modifié ultérieurement."
                    },
                    "vat_validation_status": {
                      "type": "string",
                      "enum": [
                        "valid",
                        "invalid",
                        "format_valid",
                        "invalid_format",
                        "could_not_validate",
                        "not_applicable"
                      ],
                      "description": "Résultat de la validation du numéro de TVA ou, s'il n'y en a pas, du `tax_number`, lors de la soumission au registre. `valid` / `invalid` : déterminé par le registre officiel du pays (VIES UE, Norvège, Suisse, Brésil, Colombie, Costa Rica, Équateur, Paraguay ; Pologne également par son registre national de TVA). `format_valid` / `invalid_format` : déterminé par les règles de format et de chiffre de contrôle du pays lorsqu'aucun registre ne peut être interrogé. `could_not_validate` : le registre était indisponible. `not_applicable` : pas de numéro, un pays sans registre ni règles, ou une session sandbox."
                    },
                    "vat_validated_number": {
                      "type": "string",
                      "nullable": true,
                      "description": "Le numéro qui a été vérifié, tel que la source le connaît (par exemple le numéro de TVA dérivé d'un SIREN français ou d'un RSIN néerlandais). `null` si aucune vérification n'a été effectuée."
                    },
                    "vat_validation_source": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "eu_vies",
                        "pl_vat_white_list",
                        "no_brreg",
                        "ch_uid_register",
                        "br_receita_federal",
                        "co_rues",
                        "cr_hacienda",
                        "ec_sri",
                        "py_dnit",
                        "format_rules",
                        null
                      ],
                      "description": "La source ayant déterminé `vat_validation_status` : un registre officiel ou `format_rules`. Vaut `null` si aucune vérification n'a été exécutée."
                    },
                    "vat_validated_name": {
                      "type": "string",
                      "nullable": true,
                      "description": "Nom enregistré auprès de la source ayant validé le numéro, lorsqu'elle en communique un. Défini uniquement lorsque le statut est `valid`."
                    },
                    "vat_validated_address": {
                      "type": "string",
                      "nullable": true,
                      "description": "Adresse enregistrée auprès de la source ayant validé le numéro, lorsqu'elle en divulgue une. Renseigné uniquement lorsque le statut est `valid`."
                    },
                    "vat_checked_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Horodatage de la vérification. `null` si aucune vérification n'a été exécutée."
                    },
                    "financial_summary": {
                      "type": "object",
                      "nullable": true
                    },
                    "officers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "designation": {
                            "type": "string",
                            "nullable": true
                          },
                          "role": {
                            "type": "string",
                            "nullable": true
                          },
                          "nationality": {
                            "type": "string",
                            "nullable": true
                          },
                          "is_active": {
                            "type": "boolean"
                          },
                          "kyc_status": {
                            "type": "string",
                            "enum": [
                              "Approved",
                              "Declined",
                              "Pending"
                            ],
                            "nullable": true
                          },
                          "kyc_session_url": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true
                          },
                          "first_name": {
                            "type": "string",
                            "nullable": true,
                            "description": "Prénom lorsqu'il est explicitement indiqué par le registre ; non déduit du nom complet."
                          },
                          "last_name": {
                            "type": "string",
                            "nullable": true,
                            "description": "Nom de famille lorsqu'il est explicitement indiqué par le registre."
                          },
                          "address": {
                            "type": "string",
                            "nullable": true,
                            "description": "Adresse du dirigeant indiquée par le registre."
                          },
                          "appointment_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date à laquelle le dirigeant a été nommé.",
                            "format": "date"
                          },
                          "termination_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de fin de mandat, lorsqu'elle est signalée.",
                            "format": "date"
                          },
                          "date_of_birth": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de naissance complète rapportée par le registre. Null lorsque seuls l'année ou le mois de naissance sont connus.",
                            "format": "date"
                          },
                          "date_of_birth_year": {
                            "type": "integer",
                            "nullable": true,
                            "minimum": 1,
                            "maximum": 9999,
                            "description": "Année de naissance indiquée par le registre, y compris lorsque la date complète n'est pas disponible."
                          },
                          "date_of_birth_month": {
                            "type": "integer",
                            "nullable": true,
                            "minimum": 1,
                            "maximum": 12,
                            "description": "Mois de naissance indiqué par le registre. Null lorsque seule l'année est connue."
                          }
                        }
                      }
                    },
                    "beneficial_owners": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "first_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "entity_type": {
                            "type": "string",
                            "enum": [
                              "person",
                              "company"
                            ]
                          },
                          "roles": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "ownership_min_shares": {
                            "type": "string",
                            "nullable": true,
                            "description": "Limite inférieure du pourcentage d'actionnariat telle que déclarée par le registre. Chaîne de texte libre (par ex. `\"25.00\"`, `\"50\"`) ; utilisez `effective_ownership_percent` pour une valeur numérique analysée."
                          },
                          "ownership_max_shares": {
                            "type": "string",
                            "nullable": true,
                            "description": "Limite supérieure du pourcentage d'actionnariat tel qu'indiqué par le registre. Chaîne au format libre ; utilisez `effective_ownership_percent` pour obtenir une valeur numérique analysée."
                          },
                          "is_active": {
                            "type": "boolean"
                          },
                          "kyc_status": {
                            "type": "string",
                            "enum": [
                              "Approved",
                              "Declined",
                              "Pending"
                            ],
                            "nullable": true
                          },
                          "kyc_session_url": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true
                          },
                          "effective_ownership_percent": {
                            "type": "number",
                            "nullable": true
                          },
                          "company_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "registration_number": {
                            "type": "string",
                            "nullable": true
                          },
                          "country_of_birth": {
                            "type": "string",
                            "nullable": true
                          },
                          "email": {
                            "type": "string",
                            "nullable": true
                          },
                          "nationality": {
                            "type": "string",
                            "nullable": true
                          },
                          "designation": {
                            "type": "string",
                            "nullable": true
                          },
                          "voting_min_shares": {
                            "type": "string",
                            "nullable": true
                          },
                          "voting_max_shares": {
                            "type": "string",
                            "nullable": true
                          },
                          "date_of_birth": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de naissance complète lorsqu'elle est rapportée.",
                            "format": "date"
                          },
                          "appointment_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de nomination lorsqu'elle est déclarée.",
                            "format": "date"
                          },
                          "shareholding": {
                            "$ref": "#/components/schemas/KYBRegistryShareholding"
                          }
                        }
                      }
                    },
                    "addresses": {
                      "type": "array",
                      "nullable": true,
                      "description": "Chaque adresse indiquée par le registre, sous un format canonique unique. Nul lorsqu'il n'en indique aucune.",
                      "items": {
                        "$ref": "#/components/schemas/KYBRegistryAddress"
                      }
                    },
                    "industries": {
                      "type": "array",
                      "nullable": true,
                      "description": "Les activités dans lesquelles le registre classe l'entreprise, sous une forme canonique. Null lorsqu'il n'en indique aucune.",
                      "items": {
                        "$ref": "#/components/schemas/KYBRegistryIndustry"
                      }
                    },
                    "accounts": {
                      "type": "object",
                      "nullable": true,
                      "additionalProperties": true,
                      "description": "Dates de dépôt au registre, lorsqu'elles sont disponibles. Les déclarations annuelles et les assemblées générales utilisent last_annual_return_date et last_agm_date ; elles sont distinctes des comptes financiers."
                    },
                    "registry_data": {
                      "$ref": "#/components/schemas/KYBRegistryData"
                    },
                    "user_provided_data": {
                      "type": "object",
                      "description": "Données confirmées ou modifiées par l'utilisateur final."
                    },
                    "confirmed_by_user_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "last_console_edit_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "is_editable": {
                      "type": "boolean"
                    },
                    "ownership": {
                      "$ref": "#/components/schemas/KYBRegistryOwnership"
                    },
                    "registry_tier": {
                      "type": "string",
                      "nullable": true,
                      "description": "Le niveau de registre commandé par le workflow : `basic`, `shareholders` ou `ubo`. Également dans `ownership.tier_requested`."
                    },
                    "registry_tier_delivered": {
                      "type": "string",
                      "nullable": true,
                      "description": "Le niveau fourni par le registre et qui est facturé. Également présent dans `ownership.tier_delivered`."
                    },
                    "registry_ownership_status": {
                      "type": "string",
                      "nullable": true,
                      "description": "`not_requested`, `pending`, `delivered`, `not_held` ou `unavailable`. Également dans `ownership.status`."
                    },
                    "registry_monitoring": {
                      "type": "object",
                      "nullable": true,
                      "description": "Le moniteur de registre le plus récent pour l'entreprise, ou `null` s'il n'en existe aucun.",
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "status": {
                          "type": "string"
                        },
                        "unavailable_reason": {
                          "type": "string",
                          "nullable": true
                        },
                        "enrolled_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "cancelled_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "last_bill_date": {
                          "type": "string",
                          "format": "date",
                          "nullable": true
                        },
                        "next_bill_date": {
                          "type": "string",
                          "format": "date",
                          "nullable": true
                        },
                        "last_event_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "events_count": {
                          "type": "integer"
                        },
                        "watched_fields": {
                          "description": "Les champs de l'entreprise que le moniteur surveille."
                        }
                      }
                    }
                  }
                },
                "ownership_structure": {
                  "$ref": "#/components/schemas/KYBOwnershipStructure"
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          },
          "key_people_checks": {
            "type": "array",
            "nullable": true,
            "description": "Vérifications agrégées des personnes clés. Présent uniquement lorsque `session_kind = business`. Chaque élément utilise la structure à deux compartiments (`registry`, `submitted`, `ubo_kyc_summary`).",
            "items": {
              "type": "object",
              "description": "Vérification agrégée des dirigeants et des UBO de l'entreprise. Utilise la structure `registry` / `submitted`. Présent uniquement lorsque session_kind = business.",
              "properties": {
                "status": {
                  "type": "string"
                },
                "node_id": {
                  "type": "string",
                  "nullable": true
                },
                "registry": {
                  "type": "object",
                  "description": "Parties découvertes via la vérification du registre.",
                  "properties": {
                    "officers": {
                      "type": "array",
                      "description": "Dirigeants découverts via la vérification du registre, chacun enrichi avec le statut de toute session KYC enfant et du filtrage AML déclenchés pour eux.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string",
                            "description": "Nom complet du dirigeant tel qu'enregistré dans le registre."
                          },
                          "designation": {
                            "type": "string",
                            "nullable": true,
                            "description": "Désignation en texte libre issue du registre (par exemple `Director`, `Company Secretary`)."
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "director",
                              "non_executive_director",
                              "secretary",
                              "chairman",
                              "ubo",
                              "shareholder",
                              "representative",
                              "founder",
                              "legal_advisor",
                              "authorized_signatory",
                              "trustee",
                              "beneficiary",
                              "settlor",
                              "protector",
                              "company_officer",
                              "investor",
                              "other"
                            ],
                            "description": "Rôle normalisé du dirigeant."
                          },
                          "nationality": {
                            "type": "string",
                            "nullable": true
                          },
                          "appointment_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date à laquelle le dirigeant a été nommé.",
                            "format": "date"
                          },
                          "termination_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de fin de mandat, lorsqu'elle est signalée.",
                            "format": "date"
                          },
                          "is_active": {
                            "type": "boolean"
                          },
                          "address": {
                            "type": "string",
                            "nullable": true,
                            "description": "Adresse du dirigeant indiquée par le registre."
                          },
                          "aml_status": {
                            "type": "string",
                            "enum": [
                              "Not Finished",
                              "Approved",
                              "Declined",
                              "In Review",
                              "Resub Requested"
                            ],
                            "nullable": true,
                            "description": "Statut du filtrage AML exécuté pour ce dirigeant. `null` lorsqu'aucun filtrage AML n'a été exécuté."
                          },
                          "kyc_status": {
                            "type": "string",
                            "enum": [
                              "Not Started",
                              "In Progress",
                              "Approved",
                              "Declined",
                              "In Review",
                              "Expired",
                              "Abandoned",
                              "Kyc Expired",
                              "Resubmitted",
                              "Awaiting User"
                            ],
                            "nullable": true,
                            "description": "Statut brut du cycle de vie de la session KYC enfant générée pour ce dirigeant. Il s'agit de l'énumération complète des statuts de session (et non d'un ensemble réduit Approuvé/Refusé/En attente). `null` lorsqu'aucune session KYC enfant n'existe."
                          },
                          "kyc_session_url": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true,
                            "description": "URL partageable de la session KYC enfant. `null` lorsqu'aucune session enfant n'existe."
                          },
                          "kyc_session_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "ID de session de la session KYC enfant. Transmettez-le à ce même endpoint de décision pour récupérer le rapport KYC complet de la personne. `null` lorsqu'aucune session enfant n'existe."
                          },
                          "verification_workflow_type": {
                            "type": "string",
                            "nullable": true,
                            "description": "Type de workflow de base du workflow de la session enfant (par ex. `kyc`). `null` pour les workflows basés sur un graphe ou lorsqu'aucune session enfant n'existe."
                          },
                          "verification_workflow_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "ID du workflow utilisé par la session enfant. `null` lorsqu'aucune session enfant n'existe."
                          },
                          "verification_workflow_label": {
                            "type": "string",
                            "nullable": true,
                            "description": "Libellé lisible par l'humain du workflow de la session enfant. `null` lorsqu'il n'est pas défini."
                          },
                          "verification_workflow_features": {
                            "type": "array",
                            "nullable": true,
                            "description": "Progression par fonctionnalité de la session de vérification enfant, par ex. `[{\"feature\": \"ID_VERIFICATION\", \"status\": \"Approved\"}]`. `null` lorsque la session enfant n'a pas de liste de fonctionnalités pouvant être déterminée.",
                            "items": {
                              "type": "object",
                              "properties": {
                                "feature": {
                                  "type": "string",
                                  "description": "Nom d'affichage de la fonctionnalité (par ex. `ID_VERIFICATION`, `LIVENESS`, `AML`)."
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "Not Finished",
                                    "Approved",
                                    "Declined",
                                    "In Review",
                                    "Resub Requested"
                                  ],
                                  "description": "Statut au niveau de la fonctionnalité au sein de la session enfant."
                                }
                              }
                            }
                          },
                          "didit_internal_id": {
                            "type": "string",
                            "nullable": true,
                            "description": "Identifiant interne stable de l'individu vérifié associé à la session enfant — utile pour la liaison entre sessions. `null` lorsqu'aucune session enfant n'existe ou que l'utilisateur n'a pas encore été résolu."
                          },
                          "kyc_document_type": {
                            "type": "string",
                            "nullable": true,
                            "description": "Type de document présenté dans la session KYC enfant (ex. `P`, `ID`, `DL`). `null` tant que la session enfant n'a pas de résultat de vérification d'identité."
                          },
                          "kyc_nationality": {
                            "type": "string",
                            "nullable": true,
                            "description": "Nationalité extraite du document dans la session KYC enfant. `null` jusqu'à ce qu'elle soit disponible."
                          },
                          "kyc_liveness_passed": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Indique si le contrôle de détection du vivant de la session KYC enfant a réussi. `null` si aucun contrôle de détection du vivant n'a été exécuté."
                          },
                          "kyc_verified_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Date et heure auxquelles la session KYC enfant a atteint `Approved`. `null` tant que la session enfant a un autre statut."
                          },
                          "kyc_aml_categories": {
                            "type": "object",
                            "nullable": true,
                            "description": "Résumé par catégorie dérivé des correspondances AML de la personne. `null` lorsqu'il n'y a aucune correspondance.",
                            "properties": {
                              "sanctions": {
                                "type": "string",
                                "enum": [
                                  "match",
                                  "clear"
                                ]
                              },
                              "pep": {
                                "type": "string",
                                "enum": [
                                  "match",
                                  "clear"
                                ]
                              },
                              "adverse_media": {
                                "type": "string",
                                "enum": [
                                  "match",
                                  "clear"
                                ]
                              },
                              "warnings": {
                                "type": "string",
                                "enum": [
                                  "match",
                                  "clear"
                                ]
                              }
                            }
                          },
                          "kyc_notification_sent_at": {
                            "type": "string",
                            "nullable": true,
                            "description": "Horodatage ISO 8601 de la dernière notification d'invitation à la vérification envoyée pour la session enfant de cette personne. `null` si aucune n'a été envoyée."
                          },
                          "first_name": {
                            "type": "string",
                            "nullable": true,
                            "description": "Prénom lorsqu'il est explicitement indiqué par le registre ; non déduit du nom complet."
                          },
                          "last_name": {
                            "type": "string",
                            "nullable": true,
                            "description": "Nom de famille lorsqu'il est explicitement indiqué par le registre."
                          },
                          "date_of_birth": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de naissance complète rapportée par le registre. Null lorsque seuls l'année ou le mois de naissance sont connus.",
                            "format": "date"
                          },
                          "date_of_birth_year": {
                            "type": "integer",
                            "nullable": true,
                            "minimum": 1,
                            "maximum": 9999,
                            "description": "Année de naissance indiquée par le registre, y compris lorsque la date complète n'est pas disponible."
                          },
                          "date_of_birth_month": {
                            "type": "integer",
                            "nullable": true,
                            "minimum": 1,
                            "maximum": 12,
                            "description": "Mois de naissance indiqué par le registre. Null lorsque seule l'année est connue."
                          }
                        }
                      }
                    },
                    "beneficial_owners": {
                      "type": "array",
                      "description": "Bénéficiaires effectifs découverts via la vérification au registre, chacun enrichi du statut de toute session KYC enfant et de tout filtrage AML déclenchés pour lui.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string",
                            "description": "Nom complet du bénéficiaire effectif (ou raison sociale pour les UBO personnes morales)."
                          },
                          "first_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "date_of_birth": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de naissance complète lorsqu'elle est rapportée.",
                            "format": "date"
                          },
                          "country_of_birth": {
                            "type": "string",
                            "nullable": true
                          },
                          "email": {
                            "type": "string",
                            "nullable": true
                          },
                          "company_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "registration_number": {
                            "type": "string",
                            "nullable": true
                          },
                          "entity_type": {
                            "type": "string",
                            "enum": [
                              "person",
                              "company"
                            ]
                          },
                          "nationality": {
                            "type": "string",
                            "nullable": true
                          },
                          "designation": {
                            "type": "string",
                            "nullable": true
                          },
                          "roles": {
                            "type": "array",
                            "description": "Noms des rôles détenus par ce propriétaire, par ex. `[\"ubo\", \"shareholder\"]`.",
                            "items": {
                              "type": "string"
                            }
                          },
                          "ownership_min_shares": {
                            "type": "string",
                            "nullable": true,
                            "description": "Limite inférieure du pourcentage d'actionnariat telle que déclarée par le registre. Chaîne de texte libre (par ex. `\"25\"`, `\"25-50%\"`) ; utilisez `effective_ownership_percent` pour une valeur numérique analysée."
                          },
                          "ownership_max_shares": {
                            "type": "string",
                            "nullable": true,
                            "description": "Limite supérieure du pourcentage d'actionnariat tel qu'indiqué par le registre. Chaîne au format libre ; utilisez `effective_ownership_percent` pour obtenir une valeur numérique analysée."
                          },
                          "is_active": {
                            "type": "boolean"
                          },
                          "aml_status": {
                            "type": "string",
                            "enum": [
                              "Not Finished",
                              "Approved",
                              "Declined",
                              "In Review",
                              "Resub Requested"
                            ],
                            "nullable": true,
                            "description": "Statut du filtrage AML exécuté pour ce bénéficiaire effectif. `null` lorsqu'aucun filtrage AML n'a été exécuté."
                          },
                          "kyc_status": {
                            "type": "string",
                            "enum": [
                              "Not Started",
                              "In Progress",
                              "Approved",
                              "Declined",
                              "In Review",
                              "Expired",
                              "Abandoned",
                              "Kyc Expired",
                              "Resubmitted",
                              "Awaiting User"
                            ],
                            "nullable": true,
                            "description": "Statut brut du cycle de vie de la session KYC enfant générée pour ce bénéficiaire effectif. Il s'agit de l'énumération complète des statuts de session (et non d'un ensemble réduit Approuvé/Refusé/En attente). `null` lorsqu'aucune session KYC enfant n'existe."
                          },
                          "kyc_session_url": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true,
                            "description": "URL partageable de la session KYC enfant. `null` lorsqu'aucune session enfant n'existe."
                          },
                          "kyc_session_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "ID de session de la session KYC enfant. Transmettez-le à ce même endpoint de décision pour récupérer le rapport KYC complet de la personne. `null` lorsqu'aucune session enfant n'existe."
                          },
                          "verification_workflow_type": {
                            "type": "string",
                            "nullable": true,
                            "description": "Type de workflow de base du workflow de la session enfant (par ex. `kyc`). `null` pour les workflows basés sur un graphe ou lorsqu'aucune session enfant n'existe."
                          },
                          "verification_workflow_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "ID du workflow utilisé par la session enfant. `null` lorsqu'aucune session enfant n'existe."
                          },
                          "verification_workflow_label": {
                            "type": "string",
                            "nullable": true,
                            "description": "Libellé lisible par l'humain du workflow de la session enfant. `null` lorsqu'il n'est pas défini."
                          },
                          "verification_workflow_features": {
                            "type": "array",
                            "nullable": true,
                            "description": "Progression par fonctionnalité de la session de vérification enfant, par ex. `[{\"feature\": \"ID_VERIFICATION\", \"status\": \"Approved\"}]`. `null` lorsque la session enfant n'a pas de liste de fonctionnalités pouvant être déterminée.",
                            "items": {
                              "type": "object",
                              "properties": {
                                "feature": {
                                  "type": "string",
                                  "description": "Nom d'affichage de la fonctionnalité (par ex. `ID_VERIFICATION`, `LIVENESS`, `AML`)."
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "Not Finished",
                                    "Approved",
                                    "Declined",
                                    "In Review",
                                    "Resub Requested"
                                  ],
                                  "description": "Statut au niveau de la fonctionnalité au sein de la session enfant."
                                }
                              }
                            }
                          },
                          "didit_internal_id": {
                            "type": "string",
                            "nullable": true,
                            "description": "Identifiant interne stable de l'individu vérifié associé à la session enfant — utile pour la liaison entre sessions. `null` lorsqu'aucune session enfant n'existe ou que l'utilisateur n'a pas encore été résolu."
                          },
                          "kyc_document_type": {
                            "type": "string",
                            "nullable": true,
                            "description": "Type de document présenté dans la session KYC enfant (ex. `P`, `ID`, `DL`). `null` tant que la session enfant n'a pas de résultat de vérification d'identité."
                          },
                          "kyc_nationality": {
                            "type": "string",
                            "nullable": true,
                            "description": "Nationalité extraite du document dans la session KYC enfant. `null` jusqu'à ce qu'elle soit disponible."
                          },
                          "kyc_liveness_passed": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Indique si le contrôle de détection du vivant de la session KYC enfant a réussi. `null` si aucun contrôle de détection du vivant n'a été exécuté."
                          },
                          "kyc_verified_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "description": "Date et heure auxquelles la session KYC enfant a atteint `Approved`. `null` tant que la session enfant a un autre statut."
                          },
                          "kyc_aml_categories": {
                            "type": "object",
                            "nullable": true,
                            "description": "Résumé par catégorie dérivé des correspondances AML de la personne. `null` lorsqu'il n'y a aucune correspondance.",
                            "properties": {
                              "sanctions": {
                                "type": "string",
                                "enum": [
                                  "match",
                                  "clear"
                                ]
                              },
                              "pep": {
                                "type": "string",
                                "enum": [
                                  "match",
                                  "clear"
                                ]
                              },
                              "adverse_media": {
                                "type": "string",
                                "enum": [
                                  "match",
                                  "clear"
                                ]
                              },
                              "warnings": {
                                "type": "string",
                                "enum": [
                                  "match",
                                  "clear"
                                ]
                              }
                            }
                          },
                          "kyc_notification_sent_at": {
                            "type": "string",
                            "nullable": true,
                            "description": "Horodatage ISO 8601 de la dernière notification d'invitation à la vérification envoyée pour la session enfant de cette personne. `null` si aucune n'a été envoyée."
                          },
                          "child_beneficial_owners": {
                            "type": "array",
                            "description": "Pour les bénéficiaires effectifs d'entreprises : les propres bénéficiaires effectifs de l'entité propriétaire, sous forme d'objets bruts extraits du registre. Tableau vide si non applicable.",
                            "items": {
                              "type": "object"
                            }
                          },
                          "effective_ownership_percent": {
                            "type": "number",
                            "nullable": true,
                            "description": "Pourcentage d'actionnariat numérique analysé — la borne maximale si disponible, sinon la borne minimale. `null` lorsqu'aucune des deux bornes n'a pu être analysée."
                          },
                          "voting_min_shares": {
                            "type": "string",
                            "nullable": true
                          },
                          "voting_max_shares": {
                            "type": "string",
                            "nullable": true
                          },
                          "appointment_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de nomination lorsqu'elle est déclarée.",
                            "format": "date"
                          }
                        }
                      }
                    }
                  }
                },
                "submitted": {
                  "type": "object",
                  "description": "Parties soumises par l'administrateur de l'entreprise lors du flux des personnes clés (lignes BusinessParty où source=USER).",
                  "properties": {
                    "parties": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Partie soumise par l'administrateur de l'entreprise via le flux des personnes clés (source=USER).",
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "entity_type": {
                            "type": "string",
                            "enum": [
                              "person",
                              "company"
                            ]
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "USER"
                            ],
                            "description": "Toujours `USER` ici — ce compartiment contient uniquement les parties saisies ou confirmées par l'utilisateur final dans le flux Personnes clés (les personnes découvertes dans le registre apparaissent sous `registry`)."
                          },
                          "name": {
                            "type": "string"
                          },
                          "first_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "company_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "registration_number": {
                            "type": "string",
                            "nullable": true
                          },
                          "email": {
                            "type": "string",
                            "format": "email",
                            "nullable": true
                          },
                          "nationality": {
                            "type": "string",
                            "nullable": true,
                            "description": "Nationalité pour les personnes physiques ; pays de constitution pour les entreprises."
                          },
                          "phone_number": {
                            "type": "string",
                            "nullable": true
                          },
                          "date_of_birth": {
                            "type": "string",
                            "format": "date",
                            "nullable": true
                          },
                          "position": {
                            "type": "string",
                            "nullable": true,
                            "description": "Intitulé de poste / fonction en texte libre (personnes physiques uniquement)."
                          },
                          "custom_fields": {
                            "type": "object",
                            "description": "Champs personnalisés définis par le workflow collectés pour cette partie ; les clés sont définies par les descripteurs de champs des personnes clés du workflow."
                          },
                          "is_active": {
                            "type": "boolean"
                          },
                          "is_skipped": {
                            "type": "boolean",
                            "description": "Vrai lorsque l'utilisateur final a ignoré la vérification pour cette partie (possible uniquement lorsque le rôle autorise l'omission)."
                          },
                          "requires_verification": {
                            "type": "boolean",
                            "description": "Vrai lorsqu'une sous-session KYC / KYB enfant est requise pour cette partie en fonction des paramètres de rôle et des seuils d'actionnariat."
                          },
                          "roles": {
                            "type": "array",
                            "description": "Tous les rôles occupés par cette partie, chacun avec ses propres pourcentages d'actionnariat et de droits de vote. Il n'y a pas de champ scalaire `role`/`ownership_percent` sur la partie elle-même.",
                            "items": {
                              "type": "object",
                              "properties": {
                                "role": {
                                  "type": "string",
                                  "enum": [
                                    "director",
                                    "non_executive_director",
                                    "secretary",
                                    "chairman",
                                    "ubo",
                                    "shareholder",
                                    "representative",
                                    "founder",
                                    "legal_advisor",
                                    "authorized_signatory",
                                    "trustee",
                                    "beneficiary",
                                    "settlor",
                                    "protector",
                                    "company_officer",
                                    "investor",
                                    "other"
                                  ]
                                },
                                "ownership_percent": {
                                  "type": "number",
                                  "nullable": true
                                },
                                "voting_percent": {
                                  "type": "number",
                                  "nullable": true
                                }
                              }
                            }
                          },
                          "kyc_session_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "Identifiant de la sous-session KYC enfant pour les personnes physiques nécessitant une vérification. `null` sinon."
                          },
                          "kyc_session_status": {
                            "type": "string",
                            "enum": [
                              "Not Started",
                              "In Progress",
                              "Approved",
                              "Declined",
                              "In Review",
                              "Expired",
                              "Abandoned",
                              "Kyc Expired",
                              "Resubmitted",
                              "Awaiting User"
                            ],
                            "nullable": true,
                            "description": "Statut de cycle de vie de la session KYC enfant. `null` lorsqu'aucune session KYC enfant n'existe."
                          },
                          "kyc_session_url": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true
                          },
                          "kyb_sub_session_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "Identifiant de la sous-session KYB enfant pour les parties morales nécessitant une vérification. `null` sinon."
                          },
                          "kyb_sub_session_status": {
                            "type": "string",
                            "enum": [
                              "Not Started",
                              "In Progress",
                              "Approved",
                              "Declined",
                              "In Review",
                              "Expired",
                              "Abandoned",
                              "Kyc Expired",
                              "Resubmitted",
                              "Awaiting User"
                            ],
                            "nullable": true,
                            "description": "Statut de cycle de vie de la sous-session KYB enfant. `null` lorsqu'aucune sous-session n'existe."
                          },
                          "kyb_sub_session_url": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true,
                            "description": "URL partageable de la sous-session KYB enfant. `null` lorsqu'aucune sous-session n'existe."
                          },
                          "verification_workflow_type": {
                            "type": "string",
                            "nullable": true,
                            "description": "Type de workflow de base du workflow de la session enfant (session KYC prioritaire, avec repli sur la sous-session KYB). `null` pour les workflows basés sur un graphe ou lorsqu'aucune session enfant n'existe."
                          },
                          "verification_workflow_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "ID du workflow utilisé par la session enfant. `null` lorsqu'aucune session enfant n'existe."
                          },
                          "verification_workflow_label": {
                            "type": "string",
                            "nullable": true,
                            "description": "Libellé lisible par l'humain du workflow de la session enfant. `null` lorsqu'il n'est pas défini."
                          },
                          "verification_workflow_features": {
                            "type": "array",
                            "nullable": true,
                            "description": "Progression par fonctionnalité de la session de vérification enfant, par ex. `[{\"feature\": \"ID_VERIFICATION\", \"status\": \"Approved\"}]`. `null` lorsque la session enfant n'a pas de liste de fonctionnalités pouvant être déterminée.",
                            "items": {
                              "type": "object",
                              "properties": {
                                "feature": {
                                  "type": "string",
                                  "description": "Nom d'affichage de la fonctionnalité (par ex. `ID_VERIFICATION`, `LIVENESS`, `AML`)."
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "Not Finished",
                                    "Approved",
                                    "Declined",
                                    "In Review",
                                    "Resub Requested"
                                  ],
                                  "description": "Statut au niveau de la fonctionnalité au sein de la session enfant."
                                }
                              }
                            }
                          },
                          "didit_internal_id": {
                            "type": "string",
                            "nullable": true,
                            "description": "Identifiant interne stable de l'individu vérifié associé à la session enfant. `null` lorsqu'il n'est pas résolu."
                          }
                        }
                      }
                    }
                  }
                },
                "ubo_kyc_summary": {
                  "type": "object",
                  "nullable": true,
                  "description": "Progression KYC agrégée des UBO, ou null lorsqu'aucun UBO n'a de session KYC associée.",
                  "properties": {
                    "total": {
                      "type": "integer"
                    },
                    "approved": {
                      "type": "integer"
                    },
                    "flagged": {
                      "type": "integer",
                      "description": "UBO dont le KYC est Refusé ou En cours d'examen."
                    },
                    "pending": {
                      "type": "integer"
                    }
                  }
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          },
          "document_verifications": {
            "type": "array",
            "nullable": true,
            "description": "Vérifications de documents groupées par nœud de workflow. Présentes uniquement lorsque `session_kind = business`.",
            "items": {
              "type": "object",
              "description": "Documents groupés par nœud de workflow. Présent uniquement lorsque session_kind = business.",
              "properties": {
                "status": {
                  "type": "string"
                },
                "node_id": {
                  "type": "string",
                  "nullable": true
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "uuid": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "document_type": {
                        "type": "string",
                        "enum": [
                          "LEGAL_PRESENCE",
                          "COMPANY_DETAILS",
                          "OWNERSHIP_STRUCTURE",
                          "REPRESENTATIVES_AUTHORIZATION",
                          "OTHER"
                        ],
                        "nullable": true,
                        "description": "Groupe de documents KYB de haut niveau dans lequel le fichier a été classé. `null` tant qu'il n'est pas classé."
                      },
                      "document_subtype": {
                        "type": "string",
                        "nullable": true,
                        "description": "Sous-type spécifique détecté par OCR (par exemple `CERTIFICATE_OF_INCORPORATION`, `SHAREHOLDER_REGISTRY`) ; `UNKNOWN` lorsque l'OCR n'a pas pu classer le document avec certitude."
                      },
                      "document_group": {
                        "type": "string",
                        "enum": [
                          "LEGAL_PRESENCE",
                          "COMPANY_DETAILS",
                          "OWNERSHIP_STRUCTURE",
                          "REPRESENTATIVES_AUTHORIZATION",
                          "OTHER"
                        ],
                        "nullable": true,
                        "description": "Alias de `document_type` : le nom de groupe utilisé par `groups` et `required_groups`."
                      },
                      "file_url": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true,
                        "description": "Lien pré-signé de courte durée vers le fichier téléversé. `null` pour les emplacements réservés de demande de document créés par un analyste (`is_requested = true`) qui n'ont pas encore été complétés."
                      },
                      "original_filename": {
                        "type": "string",
                        "nullable": true,
                        "description": "Nom de fichier tel que téléversé par l'utilisateur ou l'analyste."
                      },
                      "file_size": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Taille du fichier en octets."
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "Not Finished",
                          "Approved",
                          "Declined",
                          "In Review",
                          "Resub Requested"
                        ],
                        "description": "Statut de vérification par document."
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "cross_check_result": {
                        "type": "object",
                        "nullable": true,
                        "description": "Recoupement des champs du document extraits par OCR avec le profil d'entreprise du registre. Un objet avec les sections `critical`, `non_critical` et `people`, chacune associant un nom de champ (par exemple `company_name`, `registration_number`, `incorporation_date`, `registered_address`) à un enregistrement de comparaison tel que `{\"document\": \"...\", \"registry\": \"...\", \"match\": true, \"score\": 0.97}`. `null` lorsque le document ne contenait aucune donnée OCR ou qu'aucune entreprise du registre n'était disponible pour la comparaison."
                      },
                      "document_metadata": {
                        "type": "object",
                        "nullable": true,
                        "description": "Métadonnées extraites du document d'entreprise téléversé. Lorsque l'extraction des métadonnées a réussi, les 16 clés sont toujours présentes (les valeurs individuelles sont `null` lorsqu'elles ne s'appliquent pas au type de fichier) ; l'objet entier est `null` si rien n'a pu être extrait. Pour les PDF, `overlay_manipulation` contient l'analyse médico-légale du texte superposé.",
                        "properties": {
                          "file_size": {
                            "type": "integer",
                            "nullable": true,
                            "description": "Taille du document."
                          },
                          "content_type": {
                            "type": "string",
                            "nullable": true,
                            "description": "Type de contenu du document."
                          },
                          "creation_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date à laquelle le document a été créé."
                          },
                          "modified_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date à laquelle le document a été modifié."
                          },
                          "creator": {
                            "type": "string",
                            "nullable": true,
                            "description": "Outil de création ou utilisateur enregistré dans les métadonnées du fichier (`Creator` du PDF)."
                          },
                          "producer": {
                            "type": "string",
                            "nullable": true,
                            "description": "Logiciel ayant généré le fichier (PDF `Producer`)."
                          },
                          "software": {
                            "type": "string",
                            "nullable": true,
                            "description": "Logiciel d'édition enregistré dans les métadonnées du fichier."
                          },
                          "encryption": {
                            "type": "string",
                            "nullable": true,
                            "description": "Schéma de chiffrement du fichier, lorsqu'il est chiffré."
                          },
                          "is_signed": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Indique si le document comporte une signature numérique."
                          },
                          "is_tampered": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Indique si la validation de la signature numérique a échoué (modification postérieure à la signature)."
                          },
                          "signature_info": {
                            "type": "object",
                            "nullable": true,
                            "description": "Détails de la ou des signatures numériques, le cas échéant."
                          },
                          "exif_original_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de capture originale EXIF, pour les téléversements d'images."
                          },
                          "exif_digitized_date": {
                            "type": "string",
                            "nullable": true,
                            "description": "Date de numérisation EXIF, pour les téléversements d'images."
                          },
                          "processed_by_known_editor": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Indique si les métadonnées indiquent que le fichier a transité par un éditeur d'images ou de PDF connu."
                          },
                          "has_different_creation_mod_date": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Indique si les dates de création et de modification diffèrent — un signal de modification possible (mais non concluant)."
                          },
                          "overlay_manipulation": {
                            "type": "object",
                            "nullable": true,
                            "description": "Analyse forensique de PDF pour suspicion de manipulation de texte superposé. Null lorsqu'aucune preuve de manipulation de superposition n'a été trouvée ou que le document n'était pas un PDF.",
                            "properties": {
                              "detected": {
                                "type": "boolean",
                                "description": "Indique si des preuves de manipulation de texte en superposition ont été détectées."
                              },
                              "analyzed": {
                                "type": "boolean",
                                "description": "Indique si le PDF a pu être analysé."
                              },
                              "analysis_incomplete": {
                                "type": "boolean",
                                "description": "Présent et vrai uniquement lorsque le fichier n'a pas pu être vérifié en totalité. Ce qui a été vérifié conserve ses constats lorsque c'est possible, et le document affiche l'avertissement de remplacement de texte non prouvé."
                              },
                              "signals": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Signaux d'analyse forensique qui se sont déclenchés, tels que duplicate_font_subset ou glyph_fragmentation."
                              },
                              "manipulated_regions": {
                                "type": "array",
                                "description": "Zones suspectées de manipulation selon les coordonnées de la page PDF.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "page": {
                                      "type": "integer"
                                    },
                                    "x": {
                                      "type": "number"
                                    },
                                    "y": {
                                      "type": "number"
                                    },
                                    "width": {
                                      "type": "number"
                                    },
                                    "height": {
                                      "type": "number"
                                    },
                                    "page_width": {
                                      "type": "number"
                                    },
                                    "page_height": {
                                      "type": "number"
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      },
                      "description": {
                        "type": "string",
                        "nullable": true,
                        "description": "Libellé ou motif fourni par l'analyste pour une demande de document. `null` pour les téléversements standards."
                      },
                      "is_requested": {
                        "type": "boolean",
                        "description": "Vrai pour les espaces réservés de demandes de documents créés par un analyste et en attente d'un téléversement."
                      },
                      "ocr_data": {
                        "type": "object",
                        "nullable": true
                      },
                      "is_console_upload": {
                        "type": "boolean",
                        "description": "Vrai pour les documents téléversés depuis la console plutôt que depuis le parcours de l'utilisateur final. Les téléversements depuis la console ne modifient jamais le statut global au niveau de la fonctionnalité."
                      },
                      "is_confirmed": {
                        "type": "boolean",
                        "description": "Les téléversements depuis la Console commencent à `false` et passent à `true` une fois confirmés par l'administrateur ; les téléversements par l'utilisateur final sont toujours à `true`."
                      }
                    }
                  }
                },
                "groups": {
                  "type": "object",
                  "description": "Compteurs de progression par groupe indexés par nom de groupe (par ex. legal_presence, ownership_structure).",
                  "additionalProperties": {
                    "type": "object",
                    "properties": {
                      "total": {
                        "type": "integer"
                      },
                      "approved": {
                        "type": "integer"
                      },
                      "pending": {
                        "type": "integer"
                      },
                      "declined": {
                        "type": "integer"
                      },
                      "in_review": {
                        "type": "integer"
                      },
                      "other": {
                        "type": "integer"
                      },
                      "missing": {
                        "type": "integer",
                        "description": "Espaces réservés demandés sans aucun fichier encore téléversé."
                      }
                    }
                  }
                },
                "required_groups": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          },
          "environment": {
            "type": "string",
            "enum": [
              "live",
              "sandbox"
            ],
            "description": "Indique si la session a été créée par une application de production (`live`) ou une application sandbox (`sandbox`). Les sessions sandbox sont gratuites, entièrement simulées et ne consomment jamais de crédits."
          },
          "sandbox_scenario": {
            "type": "string",
            "nullable": true,
            "description": "Le scénario sandbox avec lequel la session a été créée. `null` pour les sessions de production et pour les sessions sandbox créées sans scénario."
          },
          "resubmissions": {
            "type": "array",
            "description": "Renvoyé uniquement avec `include=resubmissions`, pour les sessions utilisateur et d'entreprise. Une entrée par demande de resoumission, de la plus ancienne à la plus récente. Chaque entrée contient les résultats renvoyés par les étapes resoumises avant la demande, afin que les soumissions antérieures restent consultables. La suppression de la session supprime toutes les soumissions.",
            "items": {
              "type": "object",
              "properties": {
                "number": {
                  "type": "integer",
                  "description": "1 pour la première resoumission de la session, 2 pour la deuxième, et ainsi de suite."
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Moment où la nouvelle soumission a été demandée."
                },
                "previous_status": {
                  "type": "string",
                  "description": "Le statut de la session juste avant la requête."
                },
                "nodes": {
                  "type": "array",
                  "description": "Les étapes du workflow renvoyées à l'utilisateur.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "node_id": {
                        "type": "string"
                      },
                      "feature": {
                        "type": "string"
                      }
                    }
                  }
                },
                "reasons": {
                  "type": "object",
                  "nullable": true,
                  "additionalProperties": {
                    "type": "string"
                  },
                  "description": "Le motif indiqué pour chaque étape, indexé par `node_id`."
                },
                "requested_by": {
                  "type": "object",
                  "nullable": true,
                  "description": "Qui a demandé la resoumission.",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    }
                  }
                },
                "results": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Ce que les étapes soumises à nouveau ont renvoyé avant la requête, sous les mêmes clés et sous la même forme que les résultats actuels de cette réponse (`id_verifications`, `nfc_verifications`, `liveness_checks`, `face_matches`, `poa_verifications`, `phone_verifications`, `email_verifications`, `aml_screenings`, `ip_analyses`, `database_validations`, `questionnaire_responses`, `document_ai_documents`, `geolocation_checks` ; pour les sessions d'entreprise également `document_verifications`). Seules les clés des étapes qui ont été renvoyées apparaissent."
                }
              }
            }
          },
          "biometric_consent": {
            "type": "object",
            "nullable": true,
            "description": "Indique si la session a requis un consentement biométrique explicite avant une capture de visage, pour quelle raison, ainsi que la preuve de la réponse. Sessions de Vérification des utilisateurs (KYC) uniquement ; le même objet figure dans la `decision` des webhooks de session. Vaut `null` lorsque la session n'a jamais été évaluée, par exemple un workflow sans capture de visage. Les champs sans valeur enregistrée sont à `null`. Un SDK natif inférieur à 4.10.0, ou qui ne transmet pas sa version, ne peut pas afficher l'étape de consentement : ses captures faciales s'exécutent comme auparavant, et une session ayant nécessité un consentement signale alors `status: \"pending\"` avec `reason: \"BIOMETRIC_CONSENT_UNSUPPORTED_SDK\"`. Voir [Consentement biométrique](/fr/getting-started/biometric-consent).",
            "properties": {
              "required": {
                "type": "boolean",
                "description": "Whether the session must collect explicit biometric consent. Never goes back to `false`."
              },
              "trigger": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "declared_state",
                  "ip_state",
                  "ip_unknown",
                  "document_issuer",
                  "forced",
                  "customer_collected"
                ],
                "description": "Raison pour laquelle le consentement est requis, ou comment il a été satisfait. `declared_state` : vous avez déclaré un État concerné (`user_state`, ou une adresse aux États-Unis dans `expected_details`). `ip_state` : l'IP de la personne se situe dans un État concerné (Illinois, Texas, Colorado). `ip_unknown` : les éléments situent la personne aux États-Unis mais l'État ne peut pas être déterminé (l'IP est aux États-Unis sans précision d'État, ou ne peut pas être localisée alors que vos informations ou le document situent la personne aux États-Unis). `document_issuer` : la pièce d'identité a été délivrée par un État concerné. `forced` : le mode de l'application est Always. `customer_collected` : vous avez transmis `biometric_consent` lors de la création de la session. `null` lorsqu'il n'est pas requis."
              },
              "status": {
                "type": "string",
                "enum": [
                  "not_required",
                  "pending",
                  "given",
                  "declined"
                ],
                "description": "`not_required` ; `pending` (requis et non fourni : la personne n'a pas encore répondu, ou `reason` explique pourquoi il n'a pas été recueilli) ; `given` ; `declined` (un refus a été enregistré et la session s'est terminée comme `Declined` ; aucun écran Didit ne propose de refus aujourd'hui)."
              },
              "given_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Moment où le consentement a été donné. Pour `customer_collected`, la valeur `given_at` que vous avez envoyée."
              },
              "declined_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Moment où un refus a été enregistré."
              },
              "text_version": {
                "type": "string",
                "nullable": true,
                "description": "Identifiant de version du texte de consentement auquel la personne a répondu, ou celui que vous avez envoyé."
              },
              "text_hash": {
                "type": "string",
                "nullable": true,
                "description": "SHA-256 (hex) du texte exact de consentement affiché, dans la langue dans laquelle il a été affiché."
              },
              "locale": {
                "type": "string",
                "nullable": true,
                "description": "Langue dans laquelle le texte de consentement a été affiché."
              },
              "policy_url": {
                "type": "string",
                "format": "uri",
                "nullable": true,
                "description": "La politique relative aux données biométriques vers laquelle renvoyait l'étape de consentement."
              },
              "step": {
                "type": "string",
                "nullable": true,
                "description": "Étape de workflow sur laquelle se trouvait la session lorsque la personne a répondu, par exemple `LIVENESS`."
              },
              "node_id": {
                "type": "string",
                "nullable": true,
                "description": "Nœud du graphe de workflow sur lequel se trouvait la session lorsque la personne a répondu."
              },
              "ip_address": {
                "type": "string",
                "nullable": true,
                "description": "IP d'où provient la réponse."
              },
              "ip_country_code": {
                "type": "string",
                "nullable": true,
                "description": "Pays ISO 3166-1 alpha-2 de l'adresse IP de la réponse."
              },
              "ip_state": {
                "type": "string",
                "nullable": true,
                "description": "Subdivision ISO 3166-2 de l'IP de la réponse, par exemple `US-IL`."
              },
              "ip_city": {
                "type": "string",
                "nullable": true,
                "description": "Ville de l'IP de la réponse."
              },
              "user_agent": {
                "type": "string",
                "nullable": true,
                "description": "Agent utilisateur de la requête associée à la réponse."
              },
              "detected_ip_address": {
                "type": "string",
                "nullable": true,
                "description": "L'IP de la personne depuis laquelle l'exigence a été évaluée pour la dernière fois. Peut différer de `ip_address` lorsque la personne a répondu sur un autre appareil."
              },
              "detected_country_code": {
                "type": "string",
                "nullable": true,
                "description": "Pays ISO 3166-1 alpha-2 de l'adresse IP détectée."
              },
              "detected_state": {
                "type": "string",
                "nullable": true,
                "description": "Subdivision ISO 3166-2 de l'IP détectée."
              },
              "detected_city": {
                "type": "string",
                "nullable": true,
                "description": "Ville de l'IP détectée."
              },
              "declared_state": {
                "type": "string",
                "nullable": true,
                "description": "Subdivision ISO 3166-2 que vous avez déclarée : `user_state`, ou l'État d'une adresse américaine dans `expected_details`."
              },
              "document_state": {
                "type": "string",
                "nullable": true,
                "description": "Subdivision ISO 3166-2 ayant délivré le document d'identité, lue lors de la capture de la pièce d'identité."
              },
              "jurisdictions": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "États américains (codes USPS, par exemple `IL`) dont la législation sur la biométrie couvre la personne. `US` lorsque les éléments indiquent que la personne se trouve aux États-Unis mais qu'aucun État n'est connu. Vide si aucun ne s'applique."
              },
              "retention_months": {
                "type": "integer",
                "nullable": true,
                "description": "La durée minimale de conservation biométrique, en mois, parmi `jurisdictions`. Vaut `null` si aucune ne s'applique."
              },
              "reason": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "BIOMETRIC_CONSENT_UNSUPPORTED_SDK",
                  "BIOMETRIC_CONSENT_DECLINED"
                ],
                "description": "`BIOMETRIC_CONSENT_UNSUPPORTED_SDK` : le consentement était requis et un SDK natif inférieur à 4.10.0, ou ne transmettant pas sa version, a capturé un visage sans l'étape de consentement ; `status` reste `pending`, ou devient `given` si la personne a accepté ultérieurement dans le flux hébergé. `BIOMETRIC_CONSENT_DECLINED` : un refus a été enregistré (il remplace le motif du SDK). `null` dans les autres cas, et toujours `null` lorsque la session ne nécessitait pas de consentement."
              },
              "decline_reason": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "BIOMETRIC_CONSENT_DECLINED"
                ],
                "description": "`BIOMETRIC_CONSENT_DECLINED` lorsqu'un refus enregistré a mis fin à la session, sinon `null`."
              },
              "face_data_deleted_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure auxquelles le refus a entraîné la suppression des images de visage, des vidéos et des gabarits biométriques de la session. `null` sauf si un refus a été enregistré."
              }
            }
          },
          "investigator": {
            "$ref": "#/components/schemas/InvestigatorBlock"
          },
          "biometric_retention": {
            "$ref": "#/components/schemas/BiometricRetention"
          },
          "fraud_check": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Le résultat d'un appel à l'API Fraud Check. `null` pour toute autre session."
          },
          "full_session_video": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL temporaire de l'enregistrement complet de la session. Renvoyée uniquement lorsque votre organisation enregistre la vidéo complète de la session."
          },
          "full_session_video_recorded_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure d'enregistrement de la session complète. Renvoyé uniquement lorsque votre organisation enregistre la vidéo complète de la session."
          }
        }
      },
      "WorkflowDetail": {
        "type": "object",
        "description": "Les champs ci-dessous sont typés ; l'objet contient également toutes les autres colonnes de la configuration du workflow (activation des fonctionnalités, seuils, actions d'avertissement, documents autorisés, rappels) sous forme de propriétés supplémentaires. Les champs qui ne s'appliquent pas au `workflow_type` sont `null`.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant par version (`settings_uuid`). Chaque version d'un workflow possède le sien."
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant stable partagé par toutes les versions du workflow. Les sessions créées avec celui-ci utilisent la dernière version publiée."
          },
          "workflow_label": {
            "type": "string",
            "description": "Nom d'affichage du workflow."
          },
          "workflow_type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "kyc",
              "kyb",
              "adaptive_age_verification",
              "biometric_authentication",
              "address_verification",
              "questionnaire_verification",
              "email_verification",
              "phone_verification",
              null
            ],
            "description": "Modèle de workflow. `null` pour les workflows sous forme de graphe créés sans modèle."
          },
          "is_default": {
            "type": "boolean",
            "description": "Indique s'il s'agit du workflow par défaut de l'application."
          },
          "is_archived": {
            "type": "boolean",
            "description": "Les workflows archivés ne peuvent pas démarrer de nouvelles sessions."
          },
          "version": {
            "type": "integer",
            "description": "Numéro de version au sein du workflow."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published"
            ],
            "description": "Les versions de brouillon sont modifiables ; les versions publiées sont immuables et utilisées pour les nouvelles sessions."
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles cette version a été publiée. `null` pour les brouillons."
          },
          "is_simple_workflow": {
            "type": "boolean",
            "description": "`true` lorsque le workflow ne comporte aucun `workflow_graph` personnalisé."
          },
          "is_editable": {
            "type": "boolean",
            "description": "`true` uniquement pour les versions `draft`."
          },
          "workflow_url": {
            "type": "string",
            "format": "uri",
            "description": "URL publique qui démarre une session avec ce workflow."
          },
          "workflow_graph": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Structure en graphe du workflow (nœuds et arêtes). `null` pour les workflows simples."
          },
          "features": {
            "type": "string",
            "description": "Fonctionnalités activées jointes par `\" + \"`, par exemple `\"OCR + LIVENESS\"`."
          },
          "total_price": {
            "type": "number",
            "nullable": true,
            "description": "Prix par session ; pour les workflows de graphe, le parcours le plus cher."
          },
          "min_price": {
            "type": "number",
            "nullable": true,
            "description": "Prix du parcours le moins cher dans le workflow."
          },
          "max_price": {
            "type": "number",
            "nullable": true,
            "description": "Prix du parcours le plus cher dans le workflow."
          },
          "special_add_on_prices": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Prix des modules complémentaires spécifiques à l'organisation, ou `null` si aucun n'est défini."
          },
          "max_retry_attempts": {
            "type": "integer",
            "description": "Réessais autorisés après une vérification refusée."
          },
          "retry_window_days": {
            "type": "integer",
            "nullable": true,
            "description": "Nombre de jours pendant lesquels les nouvelles tentatives sont autorisées."
          },
          "session_expiration_time": {
            "type": "integer",
            "description": "Secondes avant l'expiration d'une session inachevée."
          },
          "questionnaire": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Le questionnaire associé au workflow, ou `null`."
          },
          "kyb_role_settings": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Paramètres de vérification par rôle pour les personnes clés KYB."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "signature_availability": {
            "type": "object",
            "description": "Quels niveaux de Signature électronique peuvent signer actuellement. Vérifiez-le avant de définir `signature_level`. Renvoyé sur les workflows `kyc`, `kyb` et de graphe.",
            "properties": {
              "simple": {
                "type": "boolean",
                "description": "Simple est toujours disponible."
              },
              "aes": {
                "type": "boolean",
                "description": "Indique si Advanced (AES) peut signer actuellement. Tant que cette valeur est `false`, l'enregistrement d'une nouvelle étape avec `signature_level: \"aes\"` est refusé avec `aes_not_available`."
              },
              "qes": {
                "type": "boolean",
                "description": "Indique si la signature qualifiée (QES) peut signer actuellement. La valeur est `false` jusqu'à ce qu'un fournisseur qualifié soit connecté."
              }
            }
          },
          "is_bank_verification_enabled": {
            "type": "boolean",
            "description": "Indique si un workflow KYC ou KYB simple exécute la vérification bancaire. Elle s'exécute après les étapes de contact (et la vérification de localisation) et avant la validation en base de données, le filtrage AML et l'analyse IP. La vérification bancaire n'est pas encore disponible pour tous : son activation est refusée partout où elle n'est pas activée."
          },
          "bank_verification_config": {
            "type": "object",
            "additionalProperties": true,
            "description": "Paramètres de vérification bancaire d'un workflow simple, avec les mêmes clés qu'un nœud `BANK_VERIFICATION` (par exemple `bank_countries` et `bank_method_order`). Les clés inconnues sont ignorées. Chaque clé est optionnelle et une clé absente conserve sa valeur par défaut, `{}` désigne donc toutes les valeurs par défaut. Voir [Paramètres de vérification bancaire](/fr/management-api/workflows/feature-configs#vérification-bancaire).",
            "example": {}
          },
          "is_geolocation_enabled": {
            "type": "boolean",
            "description": "Indique si un workflow KYC simple exécute la vérification de localisation. Elle s'exécute après les étapes de contact et avant la vérification bancaire et la validation en base de données. Les workflows d'entreprise (KYB) ne peuvent pas l'exécuter."
          },
          "geolocation_config": {
            "type": "object",
            "additionalProperties": true,
            "description": "Paramètres de vérification de localisation d'un workflow simple, avec les mêmes clés qu'un nœud `GEOLOCATION` (par exemple `is_geolocation_geofencing_enabled` et `geolocation_max_attempts`). Les clés inconnues sont ignorées. Chaque clé est facultative et une clé absente conserve sa valeur par défaut, `{}` correspond donc à toutes les valeurs par défaut.",
            "example": {}
          }
        },
        "additionalProperties": true
      },
      "UserSessionListItem": {
        "title": "KYC session row (session_kind: user)",
        "type": "object",
        "description": "Ligne de résumé pour une session de Vérification des utilisateurs (KYC). Les champs d'identité (`full_name`, `country`, `document_type`, `portrait_image`, champs de contact) sont renseignés progressivement à mesure que l'utilisateur franchit les étapes de vérification, et sont `null` jusqu'à la fin de l'étape correspondante. Les champs restreints par la configuration response-attributes du workflow sont également renvoyés avec la valeur `null`.",
        "required": [
          "session_id",
          "session_kind",
          "session_number",
          "session_url",
          "portrait_image",
          "document_type",
          "full_name",
          "country",
          "status",
          "vendor_data",
          "didit_internal_id",
          "created_at",
          "features",
          "phone_number",
          "email_address",
          "additional_details"
        ],
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de la session de vérification. Utilisez-le avec `GET /v3/session/{sessionId}/decision/` pour récupérer l'intégralité du payload de décision.",
            "example": "5b3720ed-d429-42ef-b67f-37ea805f48ee"
          },
          "session_kind": {
            "type": "string",
            "enum": [
              "user"
            ],
            "description": "Discriminant de ligne. Vaut toujours `\"user\"` pour les lignes KYC ; les lignes de Vérification d'entreprise (KYB) ont `\"business\"` et une structure différente.",
            "example": "user"
          },
          "session_number": {
            "type": "integer",
            "description": "Numéro séquentiel lisible par l'humain de la session au sein de votre application. Également pris en compte par le paramètre `search`.",
            "example": 720
          },
          "session_url": {
            "type": "string",
            "nullable": true,
            "description": "URL de vérification hébergée que l'utilisateur final ouvre pour effectuer le parcours. `null` lorsque la session n'a pas d'URL hébergée.",
            "example": "https://verify.didit.me/session/CuXoBYCYVO5Y"
          },
          "portrait_image": {
            "type": "string",
            "nullable": true,
            "description": "URL temporaire (pré-signée) du meilleur portrait disponible : la photo de la puce NFC si disponible, sinon le portrait de la pièce d'identité, sinon l'image de référence de détection du vivant. `null` tant qu'aucun d'entre eux n'existe. Téléchargez-la rapidement ; le lien expire.",
            "example": "https://<media-host>/portraits/5b3720ed.jpg?X-Amz-Expires=3600&X-Amz-Signature=..."
          },
          "document_type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Passport",
              "Identity Card",
              "Driver's License",
              "Residence Permit",
              "Health Insurance Card",
              "Tax Card"
            ],
            "description": "Type lisible par l'utilisateur de la pièce d'identité vérifiée. `null` avant la fin de la vérification du document, et également `null` après celle-ci lorsque le code vérifié n'a pas de correspondance d'affichage (`SSC`, `WP`, `VISA`, `PSC`, `BC`, `OTHER`). Remarque : le paramètre de requête `document_type` filtre par codes courts (`P`, `ID`, `DL`, `RP`, ...), et non par ces valeurs d'affichage.",
            "example": "Passport"
          },
          "full_name": {
            "type": "string",
            "nullable": true,
            "description": "Meilleur nom complet disponible pour la session, résolu dans l'ordre : OCR du document d'identité, données soumises au filtrage AML, données soumises à la validation en base de données, justificatif de domicile, puis les informations attendues fournies lors de la création de la session. `null` lorsqu'aucun n'est encore disponible.",
            "example": "Jane Marie Doe"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "Pays ISO 3166-1 alpha-3 associé à la session, résolu dans l'ordre suivant : pays de délivrance du document d'identité, pays de délivrance de la validation en base de données, pays de délivrance du justificatif de domicile, informations attendues, puis pays du téléphone vérifié. Peut différer de la nationalité.",
            "example": "ESP"
          },
          "status": {
            "type": "string",
            "enum": [
              "Not Started",
              "In Progress",
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned",
              "Kyc Expired",
              "Resubmitted",
              "Awaiting User"
            ],
            "description": "Statut global de la session. Consultez la page [Statuts de vérification](/fr/integration/verification-statuses) pour le cycle de vie.",
            "example": "Approved"
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre identifiant pour l'utilisateur final, renvoyé exactement tel qu'il a été transmis lors de la création de la session.",
            "example": "your-user-id-123"
          },
          "didit_internal_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Identifiant interne Didit pour le profil d'utilisateur vérifié derrière cette session. Stable à travers plusieurs sessions du même utilisateur ; filtrable via le paramètre de requête `didit_internal_id`.",
            "example": "d9e78474-6c8d-4f2a-bb90-6f5c2f3a1147"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage UTC de la création de la session.",
            "example": "2026-06-09T12:26:54.328364Z"
          },
          "features": {
            "type": "array",
            "description": "Statut par fonctionnalité pour chaque étape de vérification configurée dans le workflow de la session, dans l'ordre du workflow.",
            "items": {
              "type": "object",
              "required": [
                "feature",
                "status"
              ],
              "properties": {
                "feature": {
                  "type": "string",
                  "enum": [
                    "ID_VERIFICATION",
                    "NFC",
                    "LIVENESS",
                    "FACE_MATCH",
                    "POA",
                    "QUESTIONNAIRE",
                    "EMAIL_VERIFICATION",
                    "PHONE",
                    "AML",
                    "IP_ANALYSIS",
                    "AGE_ESTIMATION",
                    "DATABASE_VALIDATION",
                    "GEOLOCATION"
                  ],
                  "description": "Identifiant de la fonctionnalité de vérification.",
                  "example": "ID_VERIFICATION"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "Not Finished",
                    "Approved",
                    "Declined",
                    "In Review",
                    "Resub Requested"
                  ],
                  "description": "Statut de cette fonctionnalité. `Not Finished` jusqu'à ce que l'étape soit terminée.",
                  "example": "Approved"
                }
              }
            }
          },
          "phone_number": {
            "type": "object",
            "nullable": true,
            "description": "Téléphone associé à la session : le téléphone vérifié lorsque la vérification du téléphone a été effectuée, sinon le téléphone de contact fourni lors de la création de la session. `null` lorsqu'aucun des deux n'existe.",
            "required": [
              "number",
              "is_verified"
            ],
            "properties": {
              "number": {
                "type": "string",
                "description": "Numéro de téléphone au format E.164.",
                "example": "+14155552671"
              },
              "is_verified": {
                "type": "boolean",
                "description": "`true` uniquement lorsque la fonctionnalité de vérification du téléphone a approuvé ce numéro.",
                "example": true
              }
            }
          },
          "email_address": {
            "type": "object",
            "nullable": true,
            "description": "E-mail associé à la session : l'e-mail vérifié lorsque la vérification de l'e-mail a été exécutée, sinon l'e-mail de contact fourni lors de la création de la session. `null` si aucun des deux n'existe.",
            "required": [
              "email",
              "is_verified"
            ],
            "properties": {
              "email": {
                "type": "string",
                "format": "email",
                "example": "jane@example.com"
              },
              "is_verified": {
                "type": "boolean",
                "description": "`true` uniquement lorsque la fonctionnalité de vérification de l'e-mail a approuvé cette adresse.",
                "example": true
              }
            }
          },
          "additional_details": {
            "type": "object",
            "nullable": true,
            "description": "Données supplémentaires compactes par fonctionnalité. Seules les fonctionnalités ayant produit des données apparaissent comme clés ; `null` lorsqu'aucune fonctionnalité n'a produit de données supplémentaires. Les champs exclus par la configuration des attributs de réponse du workflow sont omis.",
            "properties": {
              "aml": {
                "type": "object",
                "description": "Présent lorsque le filtrage AML a été exécuté.",
                "properties": {
                  "total_hits": {
                    "type": "integer",
                    "description": "Nombre de correspondances au filtrage AML.",
                    "example": 0
                  },
                  "entity_type": {
                    "type": "string",
                    "description": "Type d'entité filtrée.",
                    "example": "person"
                  },
                  "is_adverse_media_fetched": {
                    "type": "boolean",
                    "example": false
                  },
                  "screened_data": {
                    "type": "object",
                    "description": "Sous-ensemble des données ayant fait l'objet d'un filtrage. Seules les clés non vides sont incluses.",
                    "properties": {
                      "nationality": {
                        "type": "string",
                        "example": "ESP"
                      },
                      "document_number": {
                        "type": "string",
                        "example": "XX1234567"
                      },
                      "date_of_birth": {
                        "type": "string",
                        "example": "1990-05-21"
                      }
                    }
                  }
                }
              },
              "database_validation": {
                "type": "object",
                "description": "Présent lorsque la validation en base de données a été exécutée.",
                "properties": {
                  "validation_type": {
                    "type": "string",
                    "example": "DOCUMENT_VALIDATION"
                  },
                  "match_type": {
                    "type": "string",
                    "example": "FULL_MATCH"
                  },
                  "identification_number": {
                    "type": "string",
                    "description": "Numéro fiscal, personnel ou de document ayant été validé (premier disponible).",
                    "example": "12345678Z"
                  }
                }
              },
              "poa": {
                "type": "object",
                "description": "Présent lorsque le justificatif de domicile a été exécuté.",
                "properties": {
                  "document_type": {
                    "type": "string",
                    "example": "UTILITY_BILL"
                  },
                  "issuer": {
                    "type": "string",
                    "example": "Energy Co"
                  },
                  "address": {
                    "type": "string",
                    "example": "Calle Mayor 1, 28013 Madrid"
                  },
                  "name_on_document": {
                    "type": "string",
                    "example": "Jane Marie Doe"
                  }
                }
              },
              "liveness": {
                "type": "object",
                "description": "Présent lorsqu'une vérification du vivant a été exécutée.",
                "properties": {
                  "method": {
                    "type": "string",
                    "example": "PASSIVE"
                  },
                  "score": {
                    "type": "number",
                    "description": "Score de confiance de détection du vivant, arrondi à 2 décimales.",
                    "example": 0.98
                  }
                }
              },
              "face_match": {
                "type": "object",
                "description": "Présent lorsque la correspondance faciale a été exécutée.",
                "properties": {
                  "score": {
                    "type": "number",
                    "description": "Score de similarité de la correspondance faciale, arrondi à 2 décimales.",
                    "example": 0.95
                  },
                  "source_image": {
                    "type": "string",
                    "description": "URL temporaire (pré-signée) de l'image du visage source.",
                    "example": "https://<media-host>/faces/source.jpg?X-Amz-Expires=3600&..."
                  },
                  "target_image": {
                    "type": "string",
                    "description": "URL temporaire (pré-signée) de l'image du visage cible.",
                    "example": "https://<media-host>/faces/target.jpg?X-Amz-Expires=3600&..."
                  }
                }
              },
              "phone_verification": {
                "type": "object",
                "description": "Présent lorsque la vérification du téléphone a été exécutée.",
                "properties": {
                  "country_code": {
                    "type": "string",
                    "description": "Pays ISO 3166-1 alpha-2 du numéro de téléphone.",
                    "example": "US"
                  },
                  "is_temporary": {
                    "type": "boolean",
                    "example": false
                  },
                  "is_ported": {
                    "type": "boolean",
                    "example": false
                  },
                  "is_blocked": {
                    "type": "boolean",
                    "example": false
                  }
                }
              },
              "email_verification": {
                "type": "object",
                "description": "Présent lorsque la vérification de l'e-mail a été exécutée.",
                "properties": {
                  "is_breached": {
                    "type": "boolean",
                    "example": false
                  },
                  "is_disposable": {
                    "type": "boolean",
                    "example": false
                  },
                  "is_undeliverable": {
                    "type": "boolean",
                    "example": false
                  },
                  "is_blocklisted": {
                    "type": "boolean",
                    "example": false
                  }
                }
              }
            }
          },
          "assignee": {
            "type": "object",
            "nullable": true,
            "description": "Le réviseur de la Console auquel la session est assignée, ou `null` si personne ne la détient.",
            "properties": {
              "email": {
                "type": "string",
                "format": "email"
              },
              "assigned_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "waiting_since": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où la session a commencé à attendre un examen. `null` sauf si la session est `In Review`."
          },
          "sla_due_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date d'échéance de l'examen, d'après la date limite d'examen définie pour votre application dans la Console. `null` sauf si la session est `In Review` et qu'une date limite est définie."
          },
          "top_warnings": {
            "type": "array",
            "description": "Jusqu'à quelques-uns des avertissements les plus importants de la session, pour une vue de triage rapide. La liste complète se trouve dans la décision.",
            "items": {
              "type": "object",
              "properties": {
                "risk": {
                  "type": "string",
                  "description": "Code d'avertissement, par exemple `FACE_MATCH_LOW_SIMILARITY`."
                },
                "feature": {
                  "type": "string",
                  "description": "La fonctionnalité qui l'a déclenché."
                },
                "log_type": {
                  "type": "string",
                  "nullable": true,
                  "description": "`error` ou `warning` ; `null` pour une entrée héritée."
                },
                "short_description": {
                  "type": "string"
                }
              }
            }
          },
          "warnings_count": {
            "type": "integer",
            "description": "Nombre d'avertissements sur la session."
          }
        }
      },
      "BusinessSessionListItem": {
        "title": "KYB session row (session_kind: business)",
        "type": "object",
        "description": "Ligne de résumé pour une session de Vérification d'entreprise (KYB). Renvoyée uniquement lorsque `session_kind` est défini sur `business` ou `all`.",
        "required": [
          "session_id",
          "session_kind",
          "session_number",
          "status",
          "vendor_data",
          "created_at",
          "workflow_id",
          "workflow_type",
          "workflow_label",
          "company_name",
          "registration_number",
          "country"
        ],
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de la session de vérification d'entreprise.",
            "example": "8a1f63c2-1b9e-4f3a-9c41-2f6a1f0b7d52"
          },
          "session_kind": {
            "type": "string",
            "enum": [
              "business"
            ],
            "description": "Discriminant de ligne. Vaut toujours `\"business\"` pour les lignes KYB.",
            "example": "business"
          },
          "session_number": {
            "type": "integer",
            "description": "Numéro séquentiel lisible par l'humain de la session d'entreprise au sein de votre application. Numéroté indépendamment des sessions KYC.",
            "example": 42
          },
          "status": {
            "type": "string",
            "enum": [
              "Not Started",
              "In Progress",
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned",
              "Kyc Expired",
              "Resubmitted",
              "Awaiting User"
            ],
            "description": "Statut global de la session. Consultez la page [Statuts de vérification](/fr/integration/verification-statuses).",
            "example": "Approved"
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre identifiant pour l'entreprise, renvoyé exactement tel qu'il a été transmis lors de la création de la session.",
            "example": "your-company-id-77"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage UTC de la création de la session.",
            "example": "2026-06-08T09:14:02.118450Z"
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Identifiant du workflow avec lequel cette session a été créée.",
            "example": "9f9b1234-aaaa-bbbb-cccc-1234567890ab"
          },
          "workflow_type": {
            "type": "string",
            "nullable": true,
            "description": "Type de workflow. `kyb` pour les workflows d'entreprise.",
            "example": "kyb"
          },
          "workflow_label": {
            "type": "string",
            "nullable": true,
            "description": "Nom d'affichage du workflow.",
            "example": "Standard KYB"
          },
          "company_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de l'entreprise en cours de vérification, issu de l'entreprise du registre liée à la session. `null` jusqu'à ce qu'une entreprise soit sélectionnée.",
            "example": "Acme Holdings S.L."
          },
          "registration_number": {
            "type": "string",
            "nullable": true,
            "description": "Numéro d'immatriculation de l'entreprise provenant de l'entreprise du registre des sociétés liée à la session.",
            "example": "B12345678"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "Code pays de l'entreprise du registre liée à la session.",
            "example": "ES"
          }
        }
      },
      "TransactionVerificationSessionAction": {
        "title": "Verification session",
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "verification_session"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL de vérification hébergée à ouvrir pour l'utilisateur final."
          },
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de la session de vérification."
          },
          "session_token": {
            "type": "string",
            "description": "Token de session, utilisé par les SDK mobiles pour lancer le flux nativement."
          },
          "status": {
            "type": "string",
            "description": "Statut de la session de vérification."
          }
        },
        "required": [
          "type",
          "url"
        ]
      },
      "TransactionWalletOwnershipAction": {
        "title": "Wallet ownership",
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "wallet_ownership"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL hébergée du widget de preuve de possession du portefeuille. Ouvrez-la dans une véritable interface de navigateur - sur mobile, utilisez SFSafariViewController ou un Chrome Custom Tab, jamais une webview intégrée."
          },
          "widget_session_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de session du widget de propriété de portefeuille."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles la session du widget expire."
          }
        },
        "required": [
          "type",
          "url"
        ]
      },
      "TransactionRuleActionAddScore": {
        "type": "object",
        "required": [
          "type",
          "value"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "add_score"
            ]
          },
          "value": {
            "type": "integer",
            "description": "Points ajoutés au score de risque de la transaction. Peut être négatif."
          }
        },
        "description": "Ajoutez des points au score de risque cumulé de la transaction ; le total détermine le statut via les seuils d'examen/refus de l'application."
      },
      "TransactionRuleActionChangeStatus": {
        "type": "object",
        "required": [
          "type",
          "value"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "change_status"
            ]
          },
          "value": {
            "type": "string",
            "enum": [
              "APPROVED",
              "IN_REVIEW",
              "DECLINED",
              "AWAITING_USER"
            ],
            "description": "Statut à définir immédiatement, indépendamment du score. Clé alias : status."
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "description": "REQUIS lorsque la valeur est AWAITING_USER : le workflow de vérification que la personne concernée est invitée à effectuer. Clé d'alias : remediation_workflow_id. Didit crée une session de remédiation hébergée pour la personne concernée lorsque la règle se déclenche."
          }
        },
        "description": "Définit directement le statut de la transaction. DECLINED l'emporte toujours sur l'ensemble des règles correspondantes."
      },
      "TransactionRuleActionAddTags": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "add_tags"
            ]
          },
          "tag_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Tag d'application existant à associer."
          },
          "tag_name": {
            "type": "string",
            "description": "Nom du tag à associer ; créé à la première utilisation (stocké en majuscules). Fournissez tag_uuid ou tag_name."
          },
          "tag_color": {
            "type": "string",
            "description": "Couleur hexadécimale utilisée lorsque tag_name crée une nouvelle étiquette, par exemple #007AFE."
          }
        },
        "description": "Associer un tag d'application à la transaction correspondante."
      },
      "TransactionRuleActionAddNote": {
        "type": "object",
        "required": [
          "type",
          "note"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "add_note"
            ]
          },
          "note": {
            "type": "string",
            "description": "Texte de la note associée à la transaction (auteur : Moteur de règles). Clé d'alias : valeur."
          }
        },
        "description": "Associer une note d'analyste automatisée à la transaction correspondante."
      },
      "TransactionRuleActionAddToList": {
        "type": "object",
        "required": [
          "type",
          "list_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "add_to_list"
            ]
          },
          "list_id": {
            "type": "string",
            "format": "uuid",
            "description": "Liste à laquelle ajouter le vendor_data du sujet."
          }
        },
        "description": "Ajouter le vendor_data du sujet à une liste de blocage, une liste d'autorisation ou une liste personnalisée."
      },
      "TransactionRuleActionOpenCase": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "open_case"
            ]
          },
          "blueprint": {
            "type": "string",
            "format": "uuid",
            "description": "UUID du modèle de dossier (blueprint) ; la valeur par défaut est le modèle par défaut de l'application."
          },
          "grouping": {
            "type": "string",
            "enum": [
              "by_applicant",
              "by_rule_and_applicant"
            ],
            "description": "Indique si les correspondances répétées rejoignent un dossier par demandeur ou un par règle+demandeur."
          },
          "attach_matched_transaction": {
            "type": "boolean",
            "description": "Associer la transaction correspondante au dossier."
          }
        },
        "description": "Ouvrir (ou ajouter à) un dossier d'investigation. Seule la première action open_case sur une règle est appliquée."
      },
      "KYBRegistrySearchResults": {
        "type": "object",
        "properties": {
          "companies": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kyb_response_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "Identifiant pour ce candidat — transmettez-le à `POST /v3/kyb/select/` pour récupérer le profil complet. Éphémère et limité à cette recherche : ne le stockez pas à long terme ; relancez une recherche pour en obtenir un nouveau.",
                  "example": "69aeeb95febb0f1704042259"
                },
                "name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Raison sociale enregistrée.",
                  "example": "Tesco PLC"
                },
                "registration_number": {
                  "type": "string",
                  "nullable": true,
                  "description": "Numéro d'immatriculation au registre.",
                  "example": "00445790"
                },
                "status": {
                  "type": "string",
                  "nullable": true,
                  "description": "Statut normalisé de l'entreprise auprès du registre (par exemple `active`, `dissolved`, `inactive`, `struck off`).",
                  "example": "active"
                },
                "type": {
                  "type": "string",
                  "nullable": true,
                  "description": "Forme juridique telle que déclarée par le registre.",
                  "example": "Public Limited Company"
                },
                "registered_address": {
                  "type": "string",
                  "nullable": true,
                  "description": "Adresse enregistrée du candidat, lorsque le registre en renvoie une. Utilisez-la, avec le numéro d'immatriculation, pour distinguer les entreprises homonymes : aux États-Unis, un candidat peut être répertorié dans l'État où l'entreprise opère plutôt que dans celui que vous avez recherché.",
                  "example": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, AL7 1GA"
                },
                "risk_level": {
                  "type": "string",
                  "nullable": true,
                  "description": "Niveau de risque indiqué par le registre, lorsqu'il est disponible. Généralement `null` au moment de la recherche."
                },
                "fetch_status": {
                  "type": "string",
                  "nullable": true,
                  "description": "Toujours `pending` pour les candidats issus de la recherche — le profil complet de l'entreprise n'est récupéré (et facturé) que lorsque vous sélectionnez le candidat.",
                  "example": "pending"
                }
              }
            },
            "description": "Liste de candidats dédupliquée. Vide tant que `search_resolved=false` (mode webhook) ou lorsqu'aucun résultat ne correspond."
          },
          "pagination": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "description": "Nombre de candidats retournés."
              },
              "page": {
                "type": "integer"
              },
              "per_page": {
                "type": "integer",
                "example": 25
              }
            }
          },
          "search_status": {
            "type": "string",
            "nullable": true,
            "enum": [
              "pending",
              "resolved"
            ],
            "description": "Statut du cycle de vie de la recherche au registre."
          },
          "search_resolved": {
            "type": "boolean",
            "description": "`true` dès que la liste de candidats est définitive."
          }
        }
      },
      "KYBRegistryCandidateRequest": {
        "type": "object",
        "required": [
          "kyb_response_id"
        ],
        "properties": {
          "kyb_response_id": {
            "type": "string",
            "maxLength": 1024,
            "description": "Identifiant de candidat issu de `POST /v3/kyb/search/` (`kyb_registry.companies[].kyb_response_id`). Éphémère : utilisez-le peu de temps après la recherche qui l'a produit. Les identifiants peuvent être longs, stockez et envoyez donc la valeur exactement telle qu'elle a été renvoyée, sans supprimer les espaces superflus ni présumer de sa longueur.",
            "example": "69aeeb95febb0f1704042259"
          },
          "vendor_data": {
            "type": "string",
            "description": "Votre identifiant pour cette entreprise ; renvoyé en écho et conservé avec la session d'entreprise."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "description": "JSON libre stocké avec la session d'entreprise et renvoyé en écho."
          },
          "save_api_request": {
            "type": "boolean",
            "default": true,
            "description": "Doit être `true` (valeur par défaut). Les sélections du registre KYB sont toujours conservées afin que la facturation et la récupération puissent être suivies ; `false` renvoie `400`."
          }
        }
      },
      "WebhookEventEnvelope": {
        "type": "object",
        "description": "Champs que Didit ajoute à chaque livraison de webhook signée, quel que soit le type d'événement. Lisez `webhook_type` pour savoir quel payload vous avez reçu.",
        "required": [
          "event_id",
          "webhook_type",
          "timestamp",
          "created_at",
          "application_id",
          "environment"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de l'événement. Chaque destination reçoit la même valeur et une nouvelle livraison la conserve, utilisez-la donc pour dédupliquer."
          },
          "webhook_type": {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          "timestamp": {
            "type": "integer",
            "description": "Temps Unix en secondes auquel cette livraison a été signée. Égal à l'en-tête `X-Timestamp` ; une nouvelle livraison comporte une nouvelle valeur."
          },
          "created_at": {
            "type": "integer",
            "description": "Temps Unix en secondes de la modification ayant généré l'événement."
          },
          "application_id": {
            "type": "string",
            "format": "uuid",
            "description": "L'application à laquelle appartient l'événement."
          },
          "environment": {
            "type": "string",
            "enum": [
              "live",
              "sandbox"
            ],
            "description": "`sandbox` pour les sessions sandbox et les applications sandbox, sinon `live`."
          }
        }
      },
      "SessionWebhookEventData": {
        "type": "object",
        "description": "Champs de session `status.updated` et `data.updated`. Les champs facultatifs sont omis, jamais envoyés avec la valeur `null`, lorsqu'ils ne s'appliquent pas. Les sessions d'entreprise (KYB) ajoutent `business_session_id`, `session_kind` et `vendor_business_id`.",
        "required": [
          "session_id",
          "status",
          "sandbox_scenario"
        ],
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "La session de vérification."
          },
          "business_session_id": {
            "type": "string",
            "format": "uuid",
            "description": "Sessions entreprise (KYB) uniquement : la même valeur que `session_id`."
          },
          "session_kind": {
            "type": "string",
            "enum": [
              "business"
            ],
            "description": "Sessions entreprise (KYB) uniquement. Les événements de session utilisateur (KYC) ne comportent pas de `session_kind` au niveau racine ; lisez plutôt `decision.session_kind`."
          },
          "status": {
            "type": "string",
            "enum": [
              "Not Started",
              "In Progress",
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned",
              "Kyc Expired",
              "Resubmitted",
              "Awaiting User"
            ],
            "description": "Statut de la session après le changement."
          },
          "trigger": {
            "type": "string",
            "description": "Présent lorsque l'événement n'a pas été produit par le flux de vérification lui-même, par exemple `manual_review`, `manual_step_update`, `ongoing_monitoring`, `webhook_reconciliation` (un `status.updated` renvoyé parce que le premier webhook final n'a jamais été créé, vous pouvez donc recevoir un deuxième événement pour une décision déjà obtenue : dédupliquez sur `session_id` et `status`), `manual_webhook_recovery`, `kyb_registry_change`, `biometric_retention` (un `data.updated` envoyé lorsque les données biométriques en direct de la session sont supprimées comme prévu) ou une modification `console_*` telle que `console_registry_edit`, `console_key_people_skip` ou `console_key_people_regenerate`."
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "description": "Le workflow de la session. Omis lorsque la session n'en a pas."
          },
          "workflow_version": {
            "type": "integer",
            "description": "Version du workflow exécuté par la session. Envoyée avec `workflow_id`."
          },
          "vendor_data": {
            "type": "string",
            "description": "Votre `vendor_data` pour la session. Omis lorsqu'il est vide."
          },
          "vendor_business_id": {
            "type": "string",
            "description": "Sessions entreprise (KYB) uniquement : l'entreprise à laquelle appartient la session. Omis lorsqu'il n'y en a aucune."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Les `metadata` de votre session. Omises si elles sont vides."
          },
          "decision": {
            "$ref": "#/components/schemas/SessionDecision"
          },
          "resubmit_info": {
            "type": "object",
            "description": "Uniquement lorsque `status` est `Resubmitted` : les étapes que l'utilisateur doit recommencer et la raison.",
            "required": [
              "nodes_to_resubmit",
              "reasons"
            ],
            "properties": {
              "nodes_to_resubmit": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "node_id",
                    "feature"
                  ],
                  "properties": {
                    "node_id": {
                      "type": "string",
                      "description": "Identifiant du nœud tel qu'il apparaît dans la définition du workflow de la session (par exemple `feature_ocr`, `feature_liveness`).",
                      "example": "feature_poa"
                    },
                    "feature": {
                      "type": "string",
                      "description": "Type de fonctionnalité du nœud, par exemple `OCR`, `LIVENESS` ou `PROOF_OF_ADDRESS`.",
                      "example": "PROOF_OF_ADDRESS"
                    }
                  }
                },
                "description": "Étapes du workflow que l'utilisateur doit recommencer. Les mêmes entrées `{node_id, feature}` que `nodes_to_resubmit` dans [Update Status](#patch-/v3/session/-sessionId-/update-status/)."
              },
              "reasons": {
                "type": "object",
                "additionalProperties": true,
                "description": "Motif par `node_id` dans `nodes_to_resubmit`."
              }
            }
          },
          "sandbox_scenario": {
            "type": "string",
            "nullable": true,
            "description": "Le résultat simulé configuré sur une session sandbox, ou `null`. Vaut toujours `null` pour les sessions de production."
          }
        }
      },
      "SessionStatusUpdatedEvent": {
        "description": "Une session de vérification a changé de statut. `decision` est envoyé uniquement pour `Approved`, `Declined`, `In Review` et `Abandoned` ; il a la structure de `GET /v3/session/{sessionId}/decision/` pour les destinations sur la version 3 des webhooks (par défaut), et l'ancienne structure réduite pour les destinations de version 1 ou 2. Les sessions d'entreprise reçoivent toujours la décision d'entreprise en version 3.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "$ref": "#/components/schemas/SessionWebhookEventData"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "status.updated"
                ],
                "description": "Toujours `status.updated`."
              }
            },
            "required": [
              "webhook_type"
            ]
          }
        ]
      },
      "SessionDataUpdatedEvent": {
        "description": "Données d'une session de vérification modifiées sans changement de statut, par exemple après une modification lors d'un examen manuel, le forçage d'une étape ou un nouveau filtrage de surveillance continue. `decision` n'est envoyée que pour `Approved`, `Declined`, `In Review` et `Abandoned` ; elle a la structure de `GET /v3/session/{sessionId}/decision/` pour les destinations configurées sur la version 3 des webhooks (version par défaut), et l'ancienne structure réduite pour les destinations en version 1 ou 2. Les sessions d'entreprise reçoivent toujours la décision d'entreprise de version 3.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "$ref": "#/components/schemas/SessionWebhookEventData"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "data.updated"
                ],
                "description": "Toujours `data.updated`."
              }
            },
            "required": [
              "webhook_type"
            ]
          }
        ]
      },
      "UserStatusUpdatedEvent": {
        "description": "Un utilisateur a changé de statut. Non envoyé lors de la création de l'utilisateur.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "user.status.updated"
                ],
                "description": "Toujours `user.status.updated`."
              },
              "vendor_user_id": {
                "type": "string",
                "format": "uuid",
                "description": "L'utilisateur concerné par l'événement."
              },
              "vendor_data": {
                "type": "string",
                "nullable": true,
                "description": "Votre `vendor_data` pour l'utilisateur, ou `null`."
              },
              "status": {
                "type": "string",
                "enum": [
                  "ACTIVE",
                  "IN_REVIEW",
                  "FLAGGED",
                  "BLOCKED"
                ],
                "description": "Statut de l'utilisateur après la modification."
              },
              "previous_status": {
                "type": "string",
                "enum": [
                  "ACTIVE",
                  "IN_REVIEW",
                  "FLAGGED",
                  "BLOCKED"
                ],
                "description": "Statut avant la modification."
              }
            },
            "required": [
              "webhook_type",
              "vendor_user_id",
              "vendor_data",
              "status",
              "previous_status"
            ]
          }
        ]
      },
      "UserDataUpdatedEvent": {
        "description": "Champs d'un utilisateur modifiés. Non envoyé lors de la création de l'utilisateur. Une seule sauvegarde peut générer à la fois un événement de statut et un événement de données.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "user.data.updated"
                ],
                "description": "Toujours `user.data.updated`."
              },
              "vendor_user_id": {
                "type": "string",
                "format": "uuid",
                "description": "L'utilisateur concerné par l'événement."
              },
              "vendor_data": {
                "type": "string",
                "nullable": true,
                "description": "Votre `vendor_data` pour l'utilisateur, ou `null`."
              },
              "status": {
                "type": "string",
                "enum": [
                  "ACTIVE",
                  "IN_REVIEW",
                  "FLAGGED",
                  "BLOCKED"
                ],
                "description": "Statut de l'utilisateur après la modification."
              },
              "changed_fields": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "vendor_data",
                    "display_name",
                    "full_name",
                    "date_of_birth",
                    "metadata",
                    "portrait_image",
                    "issuing_states",
                    "approved_emails",
                    "approved_phones",
                    "features",
                    "session_count",
                    "approved_count",
                    "declined_count",
                    "in_review_count",
                    "first_session_at",
                    "last_session_at"
                  ]
                },
                "description": "Noms des champs modifiés."
              },
              "changes": {
                "type": "object",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "previous": {
                      "nullable": true,
                      "description": "Valeur avant la modification. Les dates sont des chaînes ISO 8601."
                    },
                    "current": {
                      "nullable": true,
                      "description": "Valeur après la modification. Les dates sont des chaînes ISO 8601."
                    }
                  }
                },
                "description": "Valeur précédente et actuelle de chaque champ modifié, indexée par nom de champ. Les valeurs peuvent être des données personnelles (noms, dates de naissance, liens vers le portrait, e-mails, numéros de téléphone) ; traitez-les en conséquence."
              }
            },
            "required": [
              "webhook_type",
              "vendor_user_id",
              "vendor_data",
              "status",
              "changed_fields",
              "changes"
            ]
          }
        ]
      },
      "BusinessStatusUpdatedEvent": {
        "description": "Une entreprise a changé de statut. Non envoyé lorsque l'entreprise est créée.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "business.status.updated"
                ],
                "description": "Toujours `business.status.updated`."
              },
              "vendor_business_id": {
                "type": "string",
                "format": "uuid",
                "description": "L'entreprise concernée par l'événement."
              },
              "vendor_data": {
                "type": "string",
                "nullable": true,
                "description": "Votre `vendor_data` pour l'entreprise, ou `null`."
              },
              "status": {
                "type": "string",
                "enum": [
                  "ACTIVE",
                  "IN_REVIEW",
                  "FLAGGED",
                  "BLOCKED"
                ],
                "description": "Statut de l'entreprise après la modification."
              },
              "previous_status": {
                "type": "string",
                "enum": [
                  "ACTIVE",
                  "IN_REVIEW",
                  "FLAGGED",
                  "BLOCKED"
                ],
                "description": "Statut avant la modification."
              }
            },
            "required": [
              "webhook_type",
              "vendor_business_id",
              "vendor_data",
              "status",
              "previous_status"
            ]
          }
        ]
      },
      "BusinessDataUpdatedEvent": {
        "description": "Champs d'une entreprise modifiés. Non envoyé lors de la création de l'entreprise. Une seule sauvegarde peut générer à la fois un événement de statut et un événement de données.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "business.data.updated"
                ],
                "description": "Toujours `business.data.updated`."
              },
              "vendor_business_id": {
                "type": "string",
                "format": "uuid",
                "description": "L'entreprise concernée par l'événement."
              },
              "vendor_data": {
                "type": "string",
                "nullable": true,
                "description": "Votre `vendor_data` pour l'entreprise, ou `null`."
              },
              "status": {
                "type": "string",
                "enum": [
                  "ACTIVE",
                  "IN_REVIEW",
                  "FLAGGED",
                  "BLOCKED"
                ],
                "description": "Statut de l'entreprise après la modification."
              },
              "changed_fields": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "vendor_data",
                    "display_name",
                    "metadata",
                    "legal_name",
                    "registration_number",
                    "country_code",
                    "session_count",
                    "approved_count",
                    "declined_count",
                    "in_review_count",
                    "features",
                    "first_session_at",
                    "last_session_at"
                  ]
                },
                "description": "Noms des champs modifiés."
              },
              "changes": {
                "type": "object",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "previous": {
                      "nullable": true,
                      "description": "Valeur avant la modification. Les dates sont des chaînes ISO 8601."
                    },
                    "current": {
                      "nullable": true,
                      "description": "Valeur après la modification. Les dates sont des chaînes ISO 8601."
                    }
                  }
                },
                "description": "Valeur précédente et actuelle de chaque champ modifié, indexée par nom de champ."
              }
            },
            "required": [
              "webhook_type",
              "vendor_business_id",
              "vendor_data",
              "status",
              "changed_fields",
              "changes"
            ]
          }
        ]
      },
      "TransactionCreatedEvent": {
        "description": "Une transaction a été créée et filtrée. Envoyé uniquement pour les applications de production.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "transaction.created"
                ],
                "description": "Toujours `transaction.created`."
              },
              "transaction_id": {
                "type": "string",
                "format": "uuid",
                "description": "Identifiant Didit de la transaction."
              },
              "txn_id": {
                "type": "string",
                "nullable": true,
                "description": "Le `transaction_id` que vous avez fourni lors de la création, ou `null`."
              },
              "status": {
                "type": "string",
                "enum": [
                  "APPROVED",
                  "IN_REVIEW",
                  "DECLINED",
                  "AWAITING_USER"
                ],
                "description": "État de la surveillance après la modification."
              },
              "score": {
                "type": "integer",
                "description": "Score de risque cumulé par les règles."
              },
              "severity": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "UNKNOWN",
                  "LOW",
                  "MEDIUM",
                  "HIGH",
                  "CRITICAL",
                  null
                ],
                "description": "Gravité du risque, ou `null` jusqu'à ce qu'une règle ou un fournisseur en définisse une."
              },
              "amount": {
                "type": "string",
                "description": "Montant de la transaction sous forme de chaîne décimale. Contrairement à l'API, il n'est pas normalisé et peut donc comporter des zéros de fin (jusqu'à 18 décimales)."
              },
              "currency": {
                "type": "string",
                "description": "Code devise ou symbole d'actif crypto de `amount`."
              },
              "direction": {
                "type": "string",
                "enum": [
                  "INBOUND",
                  "OUTBOUND"
                ],
                "description": "Direction par rapport au sujet."
              },
              "action_required": {
                "type": "object",
                "nullable": true,
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/TransactionVerificationSessionAction"
                  },
                  {
                    "$ref": "#/components/schemas/TransactionWalletOwnershipAction"
                  }
                ],
                "discriminator": {
                  "propertyName": "type",
                  "mapping": {
                    "verification_session": "#/components/schemas/TransactionVerificationSessionAction",
                    "wallet_ownership": "#/components/schemas/TransactionWalletOwnershipAction"
                  }
                },
                "description": "Action en attente de l'utilisateur final, ou `null`. Même objet que `action_required` sur la transaction ; `session_token` est une donnée d'authentification, ne l'enregistrez donc jamais dans les journaux."
              }
            },
            "required": [
              "webhook_type",
              "transaction_id",
              "txn_id",
              "status",
              "score",
              "severity",
              "amount",
              "currency",
              "direction",
              "action_required"
            ]
          }
        ]
      },
      "TransactionStatusUpdatedEvent": {
        "description": "Une transaction a changé de statut, à la suite d'une règle, d'un examen ou d'une action de l'utilisateur final. Envoyé uniquement pour les applications de production.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "transaction.status.updated"
                ],
                "description": "Toujours `transaction.status.updated`."
              },
              "transaction_id": {
                "type": "string",
                "format": "uuid",
                "description": "Identifiant Didit de la transaction."
              },
              "txn_id": {
                "type": "string",
                "nullable": true,
                "description": "Le `transaction_id` que vous avez fourni lors de la création, ou `null`."
              },
              "status": {
                "type": "string",
                "enum": [
                  "APPROVED",
                  "IN_REVIEW",
                  "DECLINED",
                  "AWAITING_USER"
                ],
                "description": "État de la surveillance après la modification."
              },
              "score": {
                "type": "integer",
                "description": "Score de risque cumulé par les règles."
              },
              "severity": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "UNKNOWN",
                  "LOW",
                  "MEDIUM",
                  "HIGH",
                  "CRITICAL",
                  null
                ],
                "description": "Gravité du risque, ou `null` jusqu'à ce qu'une règle ou un fournisseur en définisse une."
              },
              "amount": {
                "type": "string",
                "description": "Montant de la transaction sous forme de chaîne décimale. Contrairement à l'API, il n'est pas normalisé et peut donc comporter des zéros de fin (jusqu'à 18 décimales)."
              },
              "currency": {
                "type": "string",
                "description": "Code devise ou symbole d'actif crypto de `amount`."
              },
              "direction": {
                "type": "string",
                "enum": [
                  "INBOUND",
                  "OUTBOUND"
                ],
                "description": "Direction par rapport au sujet."
              },
              "action_required": {
                "type": "object",
                "nullable": true,
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/TransactionVerificationSessionAction"
                  },
                  {
                    "$ref": "#/components/schemas/TransactionWalletOwnershipAction"
                  }
                ],
                "discriminator": {
                  "propertyName": "type",
                  "mapping": {
                    "verification_session": "#/components/schemas/TransactionVerificationSessionAction",
                    "wallet_ownership": "#/components/schemas/TransactionWalletOwnershipAction"
                  }
                },
                "description": "Action en attente de l'utilisateur final, ou `null`. Même objet que `action_required` sur la transaction ; `session_token` est une donnée d'authentification, ne l'enregistrez donc jamais dans les journaux."
              }
            },
            "required": [
              "webhook_type",
              "transaction_id",
              "txn_id",
              "status",
              "score",
              "severity",
              "amount",
              "currency",
              "direction",
              "action_required"
            ]
          }
        ]
      },
      "TravelRuleStatusUpdatedEvent": {
        "description": "Un échange Travel Rule a changé de statut. Envoyé à chaque transition jusqu'à `FINISHED`, `CANCELLED` ou `EXPIRED` inclus, jamais après. Envoyé pour les applications en production et, pour les échanges Travel Rule, également pour les applications sandbox (`environment: sandbox`). Il n'y a pas de `status` de premier niveau.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "travel_rule.status.updated"
                ],
                "description": "Toujours `travel_rule.status.updated`."
              },
              "transaction_id": {
                "type": "string",
                "format": "uuid",
                "description": "La transaction à laquelle l'échange est associé."
              },
              "txn_id": {
                "type": "string",
                "nullable": true,
                "description": "Le `transaction_id` que vous avez fourni lors de la création, ou `null`."
              },
              "travel_rule_status": {
                "type": "string",
                "enum": [
                  "AWAITING_COUNTERPARTY",
                  "ON_HOLD",
                  "COMPLETED",
                  "FINISHED",
                  "CANCELLED",
                  "EXPIRED",
                  "COUNTERPARTY_MISMATCHED_DATA",
                  "COUNTERPARTY_VASP_NOT_FOUND",
                  "COUNTERPARTY_VASP_NOT_REACHABLE",
                  "UNCONFIRMED_OWNERSHIP",
                  "COUNTERPARTY_VASP_GENERAL_DECLINE",
                  "NOT_ENOUGH_COUNTERPARTY_DATA",
                  "NOT_APPLICABLE"
                ],
                "description": "Statut de l'échange après la modification."
              },
              "rail": {
                "type": "string",
                "enum": [
                  "",
                  "INTERNAL",
                  "TRP",
                  "GTR",
                  "TRUST",
                  "VERIFYVASP",
                  "SYGNA",
                  "EMAIL",
                  "TEST_VASP"
                ],
                "description": "Réseau sur lequel opère la plateforme d'échange, ou chaîne vide si aucun n'a pu être résolu. `TEST_VASP` est un transfert sandbox auquel le Didit Test VASP a répondu."
              },
              "test_vasp": {
                "type": "boolean",
                "description": "Présent et `true` uniquement sur un transfert en sandbox auquel le Test VASP de Didit a répondu."
              },
              "test_vasp_scenario": {
                "type": "string",
                "description": "Présent uniquement avec `test_vasp` : le scénario de sandbox qui a déterminé le résultat, ou une chaîne vide."
              },
              "direction": {
                "type": "string",
                "enum": [
                  "INBOUND",
                  "OUTBOUND"
                ],
                "description": "Direction du transfert."
              }
            },
            "required": [
              "webhook_type",
              "transaction_id",
              "txn_id",
              "travel_rule_status",
              "rail",
              "direction"
            ]
          }
        ]
      },
      "WorkflowComplianceChangedEvent": {
        "description": "Le statut de conformité d'un workflow publié a changé après une réévaluation. Un événement par workflow. Il n'y a pas de `status` au niveau supérieur.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "workflow.compliance_changed"
                ],
                "description": "Toujours `workflow.compliance_changed`."
              },
              "workflow_id": {
                "type": "string",
                "format": "uuid",
                "description": "Le workflow qui a changé."
              },
              "workflow_version": {
                "type": "integer",
                "description": "Version qui a été évaluée."
              },
              "workflow_label": {
                "type": "string",
                "nullable": true,
                "description": "Nom d'affichage du workflow."
              },
              "transition": {
                "type": "object",
                "required": [
                  "from",
                  "to"
                ],
                "properties": {
                  "from": {
                    "type": "string",
                    "enum": [
                      "compliant",
                      "gaps_detected",
                      "pending_change",
                      "unknown_coverage",
                      "not_evaluated"
                    ],
                    "description": "Statut avant la réévaluation."
                  },
                  "to": {
                    "type": "string",
                    "enum": [
                      "compliant",
                      "gaps_detected",
                      "pending_change",
                      "unknown_coverage",
                      "not_evaluated"
                    ],
                    "description": "Statut après la réévaluation."
                  }
                }
              },
              "severity": {
                "type": "string",
                "enum": [
                  "actionable",
                  "indicative",
                  "informative"
                ],
                "description": "`actionable` lorsque des écarts ont été détectés, `indicative` pour un changement en attente, `informative` lorsque les écarts ont été résolus."
              },
              "kb_version": {
                "type": "string",
                "description": "Version de la base de connaissances réglementaires utilisée."
              }
            },
            "required": [
              "webhook_type",
              "workflow_id",
              "workflow_version",
              "workflow_label",
              "transition",
              "severity",
              "kb_version"
            ]
          }
        ]
      },
      "WebhookEventPayload": {
        "description": "Corps d'une livraison de webhook signée, distingué par `webhook_type`. Il est possible de s'abonner à `activity.created`, mais cet événement n'est pas envoyé actuellement. Traitez tout autre `webhook_type` comme un nouveau type d'événement et conservez le corps brut.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/SessionStatusUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionDataUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/UserStatusUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/UserDataUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/BusinessStatusUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/BusinessDataUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/TransactionCreatedEvent"
          },
          {
            "$ref": "#/components/schemas/TransactionStatusUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/TravelRuleStatusUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/WorkflowComplianceChangedEvent"
          },
          {
            "$ref": "#/components/schemas/TransactionRuleSuggestionsCreatedEvent"
          }
        ],
        "discriminator": {
          "propertyName": "webhook_type",
          "mapping": {
            "status.updated": "#/components/schemas/SessionStatusUpdatedEvent",
            "data.updated": "#/components/schemas/SessionDataUpdatedEvent",
            "user.status.updated": "#/components/schemas/UserStatusUpdatedEvent",
            "user.data.updated": "#/components/schemas/UserDataUpdatedEvent",
            "business.status.updated": "#/components/schemas/BusinessStatusUpdatedEvent",
            "business.data.updated": "#/components/schemas/BusinessDataUpdatedEvent",
            "transaction.created": "#/components/schemas/TransactionCreatedEvent",
            "transaction.status.updated": "#/components/schemas/TransactionStatusUpdatedEvent",
            "travel_rule.status.updated": "#/components/schemas/TravelRuleStatusUpdatedEvent",
            "workflow.compliance_changed": "#/components/schemas/WorkflowComplianceChangedEvent",
            "transaction_rule_suggestions.created": "#/components/schemas/TransactionRuleSuggestionsCreatedEvent"
          }
        }
      },
      "KYBRegistrySearchResolvedCallback": {
        "type": "object",
        "description": "Corps du rappel envoyé à l'URL `webhook_url` de `POST /v3/kyb/search/` une fois la recherche dans le registre résolue. Il n'est pas signé : la requête contient `X-Didit-Unsigned-Callback: true` et aucun des en-têtes de signature, confirmez-le donc en faisant correspondre `request_id` avec une recherche que vous avez lancée. Utilise `event_type`, et non `webhook_type`.",
        "required": [
          "event_id",
          "event_type",
          "request_id",
          "vendor_data",
          "metadata",
          "search_status",
          "search_resolved",
          "kyb_registry",
          "timestamp",
          "created_at"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant du callback."
          },
          "event_type": {
            "type": "string",
            "enum": [
              "kyb.registry_search.resolved"
            ],
            "description": "Toujours `kyb.registry_search.resolved`."
          },
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Le `request_id` renvoyé par `POST /v3/kyb/search/`."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Valeur renvoyée de `vendor_data` que vous avez envoyé."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Écho des `metadata` que vous avez envoyées."
          },
          "search_status": {
            "type": "string",
            "description": "Toujours `resolved` aujourd'hui."
          },
          "search_resolved": {
            "type": "boolean",
            "description": "`true` lorsque `search_status` est `resolved`."
          },
          "kyb_registry": {
            "$ref": "#/components/schemas/KYBRegistrySearchResults"
          },
          "timestamp": {
            "type": "integer",
            "description": "Temps Unix en secondes auquel le rappel a été mis en file d'attente."
          },
          "created_at": {
            "type": "integer",
            "description": "Temps Unix en secondes auquel le rappel a été mis en file d'attente."
          }
        }
      },
      "AMLScreening": {
        "type": "object",
        "properties": {
          "node_id": {
            "type": "string",
            "description": "Identifiant unique de cette étape AML dans le graphe du workflow."
          },
          "status": {
            "type": "string",
            "description": "Statut au niveau de la fonctionnalité de ce filtrage AML. Indépendant du `status` de la session de niveau supérieur — une session peut atteindre sa décision globale tandis qu'une fonctionnalité individuelle reste `In Review`.",
            "enum": [
              "Not Finished",
              "Approved",
              "Declined",
              "In Review",
              "Resub Requested"
            ]
          },
          "total_hits": {
            "type": "integer",
            "description": "Nombre total de correspondances trouvées"
          },
          "entity_type": {
            "type": "string",
            "description": "Type d'entité filtrée : personne ou entreprise"
          },
          "hits": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Identifiant stable de Didit pour le résultat positif : `hit_` suivi de 24 caractères hexadécimaux. La même entité correspondante conserve le même `id` lorsque le sujet fait l'objet d'un nouveau filtrage. Transmettez-le en tant que `hit_id` aux endpoints d'examen des résultats AML."
                },
                "url": {
                  "type": "string",
                  "format": "uri",
                  "description": "URL source de la correspondance"
                },
                "match": {
                  "type": "boolean",
                  "description": "Indique s'il s'agit d'une correspondance confirmée"
                },
                "score": {
                  "type": "number",
                  "format": "float",
                  "nullable": true,
                  "minimum": 0,
                  "maximum": 1,
                  "description": "Score de correspondance pondéré obsolète compris entre 0 et 1 (par ex. `0.73`). Utilisez `match_score` (0-100) à la place.",
                  "deprecated": true
                },
                "target": {
                  "type": "boolean",
                  "nullable": true,
                  "description": "Indique si l'entité correspondante est la cible directe de l'inscription sur la liste (par opposition à une partie liée). `null` lorsque la source ne le précise pas."
                },
                "caption": {
                  "type": "string",
                  "description": "Légende ou titre de la correspondance"
                },
                "datasets": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "PEP",
                      "PEP Level 1",
                      "PEP Level 2",
                      "PEP Level 3",
                      "PEP Level 4",
                      "Sanctions",
                      "Adverse Media",
                      "Warnings and Regulatory Enforcement",
                      "Fitness and Probity",
                      "SIP",
                      "SIE",
                      "Insolvency",
                      "Other Lists"
                    ]
                  },
                  "description": "Liste des catégories de jeux de données où la correspondance a été trouvée. Indique si l'entité apparaît dans les listes PEP (avec le niveau), les bases de données de sanctions, la presse négative, les avertissements/mesures réglementaires ou d'autres jeux de données de conformité. Vaut `Other Lists` lorsque la source de l'entité n'indique aucune de ces catégories."
                },
                "features": {
                  "type": "object",
                  "nullable": true,
                  "description": "Caractéristiques supplémentaires de la correspondance"
                },
                "rca_name": {
                  "type": "string",
                  "description": "Nom du RCA le cas échéant"
                },
                "last_seen": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Date à laquelle la correspondance a été vue pour la dernière fois"
                },
                "risk_view": {
                  "type": "object",
                  "properties": {
                    "crimes": {
                      "type": "object",
                      "properties": {
                        "score": {
                          "type": "integer"
                        },
                        "weightage": {
                          "type": "integer"
                        },
                        "risk_level": {
                          "type": "string"
                        },
                        "risk_scores": {
                          "type": "object"
                        }
                      }
                    },
                    "countries": {
                      "type": "object",
                      "properties": {
                        "score": {
                          "type": "integer"
                        },
                        "weightage": {
                          "type": "integer"
                        },
                        "risk_level": {
                          "type": "string"
                        },
                        "risk_scores": {
                          "type": "object"
                        }
                      }
                    },
                    "categories": {
                      "type": "object",
                      "properties": {
                        "score": {
                          "type": "integer"
                        },
                        "weightage": {
                          "type": "integer"
                        },
                        "risk_level": {
                          "type": "string"
                        },
                        "risk_scores": {
                          "type": "object"
                        }
                      }
                    },
                    "custom_list": {
                      "type": "object"
                    }
                  }
                },
                "first_seen": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Date à laquelle la correspondance a été vue pour la première fois"
                },
                "properties": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "alias": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "title": {
                      "type": "string",
                      "nullable": true
                    },
                    "gender": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "height": {
                      "type": "string",
                      "nullable": true
                    },
                    "topics": {
                      "type": "string",
                      "nullable": true
                    },
                    "weight": {
                      "type": "string",
                      "nullable": true
                    },
                    "address": {
                      "type": "string",
                      "nullable": true
                    },
                    "country": {
                      "type": "string",
                      "nullable": true
                    },
                    "website": {
                      "type": "string",
                      "nullable": true
                    },
                    "eyeColor": {
                      "type": "string",
                      "nullable": true
                    },
                    "keywords": {
                      "type": "string",
                      "nullable": true
                    },
                    "lastName": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "position": {
                      "type": "string",
                      "nullable": true
                    },
                    "religion": {
                      "type": "string",
                      "nullable": true
                    },
                    "birthDate": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "education": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "ethnicity": {
                      "type": "string",
                      "nullable": true
                    },
                    "firstName": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "hairColor": {
                      "type": "string",
                      "nullable": true
                    },
                    "weakAlias": {
                      "type": "string",
                      "nullable": true
                    },
                    "birthPlace": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "modifiedAt": {
                      "type": "string",
                      "nullable": true
                    },
                    "wikidataId": {
                      "type": "string",
                      "nullable": true
                    },
                    "citizenship": {
                      "type": "string",
                      "nullable": true
                    },
                    "nationality": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                },
                "match_score": {
                  "type": "number",
                  "description": "Score de confiance d'identité pondéré (0-100) calculé à partir de la similarité de nom, de la date de naissance et de la correspondance du pays. Utilisé pour déterminer si la correspondance est un faux positif ou une correspondance possible.",
                  "format": "float",
                  "nullable": true
                },
                "risk_score": {
                  "type": "number",
                  "description": "Score de risque de l'entité (0-100). Utilisé pour déterminer le statut AML final (Approuvé / En cours d'examen / Refusé) en fonction du risk_score le plus élevé parmi les correspondances qui ne sont pas des faux positifs."
                },
                "review_status": {
                  "type": "string",
                  "description": "Statut d'examen pour ce résultat. Peut être 'Unreviewed', 'Confirmed Match', 'False Positive' ou 'Inconclusive'.",
                  "enum": [
                    "Unreviewed",
                    "Confirmed Match",
                    "False Positive",
                    "Inconclusive"
                  ]
                },
                "score_breakdown": {
                  "type": "object",
                  "description": "Ventilation détaillée du calcul du match_score.",
                  "properties": {
                    "name_score": {
                      "type": "integer",
                      "description": "Pourcentage brut de similarité des noms (0-100)."
                    },
                    "name_weight": {
                      "type": "integer",
                      "description": "Pondération d'origine pour le nom issue de la configuration (0-100)."
                    },
                    "name_weight_normalized": {
                      "type": "number",
                      "description": "Poids normalisé pour le nom après repondération pour les données manquantes (0-100)."
                    },
                    "name_contribution": {
                      "type": "number",
                      "description": "Points apportés par le nom au score total."
                    },
                    "dob_score": {
                      "type": "integer",
                      "description": "Score de correspondance de la date de naissance (-100 à 100)."
                    },
                    "dob_weight": {
                      "type": "integer",
                      "description": "Pondération d'origine pour la date de naissance issue de la configuration (0-100)."
                    },
                    "dob_weight_normalized": {
                      "type": "number",
                      "description": "Poids normalisé pour la date de naissance après repondération pour les données manquantes (0-100)."
                    },
                    "dob_contribution": {
                      "type": "number",
                      "description": "Points apportés par la date de naissance au score total."
                    },
                    "country_score": {
                      "type": "integer",
                      "description": "Score de correspondance du pays (-100 à 100)."
                    },
                    "country_weight": {
                      "type": "integer",
                      "description": "Pondération d'origine pour le pays issue de la configuration (0-100)."
                    },
                    "country_weight_normalized": {
                      "type": "number",
                      "description": "Poids normalisé pour le pays après repondération pour les données manquantes (0-100)."
                    },
                    "country_contribution": {
                      "type": "number",
                      "description": "Points apportés par le pays au score total."
                    },
                    "document_number_match_type": {
                      "type": "string",
                      "description": "Résultat de l'évaluation « Golden Key » du numéro de document.",
                      "enum": [
                        "MATCH",
                        "NEUTRAL",
                        "HARD_MISMATCH"
                      ]
                    },
                    "document_number_effect": {
                      "type": "string",
                      "description": "Description lisible par l'humain de l'effet du numéro de document sur le score."
                    },
                    "total_score": {
                      "type": "integer",
                      "description": "Score de correspondance pondéré final (0-100)."
                    }
                  }
                },
                "pep_matches": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "aliases": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "education": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "list_name": {
                        "type": "string"
                      },
                      "publisher": {
                        "type": "string"
                      },
                      "source_url": {
                        "type": "string",
                        "format": "uri"
                      },
                      "description": {
                        "type": "string"
                      },
                      "matched_name": {
                        "type": "string"
                      },
                      "pep_position": {
                        "type": "string"
                      },
                      "date_of_birth": {
                        "type": "string"
                      },
                      "other_sources": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "place_of_birth": {
                        "type": "string"
                      }
                    }
                  }
                },
                "linked_entities": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "active": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "status": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "details": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "relation": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "warning_matches": {
                  "type": "array",
                  "description": "Liste des correspondances d'avertissements et de mesures réglementaires. Comprend les entrées des catégories : Warning, SIP, Warnings and Regulatory Enforcement, Fitness and Probity, SIE et Insolvency.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "list_name": {
                        "type": "string",
                        "description": "Nom de l'éditeur de la liste d'avertissement"
                      },
                      "matched_name": {
                        "type": "string",
                        "description": "Nom correspondant dans la liste d'avertissement"
                      },
                      "description": {
                        "type": "string",
                        "description": "Description de l'entrée d'avertissement"
                      },
                      "publisher": {
                        "type": "string",
                        "description": "Émetteur ou source de l'avertissement"
                      },
                      "source_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "URL vers la source de l'avertissement"
                      },
                      "other_sources": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "URL sources supplémentaires"
                      },
                      "countries": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "nullable": true,
                        "description": "Pays associés à l'avertissement"
                      },
                      "created_at": {
                        "type": "string",
                        "nullable": true,
                        "description": "Date de création de l'entrée d'avertissement"
                      },
                      "updated_at": {
                        "type": "string",
                        "nullable": true,
                        "description": "Date de dernière mise à jour de l'entrée d'avertissement"
                      },
                      "additional_data": {
                        "type": "object",
                        "description": "Données supplémentaires issues de la source de l'avertissement. Peut contenir un objet `data` avec un tableau `case_details`.",
                        "properties": {
                          "data": {
                            "type": "object",
                            "properties": {
                              "case_details": {
                                "type": "array",
                                "description": "Détails des cas d'avertissement associés à cette correspondance",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "case_type": {
                                      "type": "string",
                                      "description": "Type du dossier d'avertissement",
                                      "enum": [
                                        "Accusation",
                                        "Arrest",
                                        "Bribery",
                                        "Criminal",
                                        "Fraud",
                                        "Illegal Fundraising",
                                        "Non-conviction Terror",
                                        "Proclaimed Offender",
                                        "Regulatory Enforcement",
                                        "Terrorism",
                                        "Terrorism-related",
                                        "Terrorism-related listing"
                                      ]
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "sanction_matches": {
                  "type": "array",
                  "description": "Liste des correspondances dans les listes de sanctions trouvées pour cette entité.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "list_name": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "nullable": true,
                        "description": "Nom(s) de la ou des listes de sanctions"
                      },
                      "matched_name": {
                        "type": "string",
                        "description": "Nom correspondant dans la liste de sanctions"
                      },
                      "description": {
                        "type": "string",
                        "description": "Description de l'entrée de sanction"
                      },
                      "reason": {
                        "type": "string",
                        "nullable": true,
                        "description": "Motif en texte libre pour lequel l'entité a été sanctionnée. Concaténé à partir des entrées de motif de la liste de sanctions. Exemples : 'Executive Order 13224 (Terrorism)', 'Support for actions undermining Ukraine's sovereignty', 'Listed due to national security concerns.'"
                      },
                      "source_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "URL vers la source de la sanction"
                      },
                      "other_sources": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "URL sources supplémentaires"
                      },
                      "details": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Détails supplémentaires sur la sanction"
                      },
                      "legal_basis": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Base juridique de la sanction"
                      },
                      "listed_on": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "nullable": true,
                        "description": "Date(s) d'inscription de l'entité sur la liste"
                      },
                      "sanction_list": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "nullable": true,
                        "description": "Identifiant(s) de liste de sanctions"
                      },
                      "sanction_program": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Programme(s) de sanctions dans le(s) cadre(s) desquel(s) l'entité est répertoriée"
                      },
                      "sanctioning_authority": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Autorité(s) ayant imposé la sanction"
                      },
                      "updated_on": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Date(s) à laquelle/auxquelles l'entrée de sanction a été mise à jour pour la dernière fois"
                      },
                      "additional_data": {
                        "type": "object",
                        "description": "Données supplémentaires issues de la source de sanctions non saisies dans les champs principaux"
                      }
                    }
                  }
                },
                "adverse_media_details": {
                  "type": "object",
                  "properties": {
                    "sentiment": {
                      "type": "string"
                    },
                    "entity_type": {
                      "type": "string"
                    },
                    "sentiment_score": {
                      "type": "integer"
                    },
                    "adverse_keywords": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "integer"
                      }
                    }
                  }
                },
                "adverse_media_matches": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "country": {
                        "type": "string"
                      },
                      "summary": {
                        "type": "string"
                      },
                      "headline": {
                        "type": "string"
                      },
                      "sentiment": {
                        "type": "string"
                      },
                      "thumbnail": {
                        "type": "string",
                        "format": "uri"
                      },
                      "source_url": {
                        "type": "string",
                        "format": "uri"
                      },
                      "author_name": {
                        "type": "string",
                        "nullable": true
                      },
                      "other_sources": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "adverse_keywords": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "sentiment_score": {
                        "type": "integer"
                      },
                      "publication_date": {
                        "type": "string",
                        "format": "date-time"
                      }
                    }
                  }
                },
                "additional_information": {
                  "type": "object"
                }
              }
            }
          },
          "score": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "minimum": 0,
            "maximum": 100,
            "description": "Score global de filtrage AML — le score de risque le plus élevé parmi toutes les correspondances (float, 0-100). `null` jusqu'à ce qu'il soit calculé."
          },
          "screened_data": {
            "type": "object",
            "properties": {
              "full_name": {
                "type": "string"
              },
              "nationality": {
                "type": "string"
              },
              "date_of_birth": {
                "type": "string",
                "format": "date"
              },
              "document_number": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "is_ongoing_monitoring_enabled": {
            "type": "boolean",
            "description": "Indique si la surveillance AML continue est activée pour ce filtrage. Lorsque défini sur `true`, l'entité fait l'objet d'un nouveau filtrage périodique et toute nouvelle correspondance met à jour le rapport."
          },
          "next_ongoing_monitoring_bill_date": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "Date (YYYY-MM-DD) à laquelle cet abonnement de surveillance continue sera facturé la prochaine fois. Calculée comme la date de la dernière facturation de surveillance continue plus 365 jours lorsque `is_ongoing_monitoring_enabled = true` ; sinon `null`. Il s'agit d'une date de facturation et non d'une date de filtrage - utilisez `last_ongoing_screening_at` pour cette dernière."
          },
          "last_ongoing_screening_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles la surveillance continue a effectué pour la dernière fois un nouveau filtrage de cet enregistrement, que le résultat ait changé ou non. `null` lorsque l'enregistrement n'a jamais fait l'objet d'un nouveau filtrage ; cette valeur n'est jamais rétroactivement renseignée à partir de la date d'activation ou de facturation."
          },
          "last_ongoing_screening_datasets_updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "La date de mise à jour du jeu de données AML la plus récente signalée par le fournisseur au moment de ce filtrage. `null` lorsque le fournisseur n'a indiqué aucune date de jeu de données ; jamais estimée."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "feature": {
                  "type": "string",
                  "enum": [
                    "ID_VERIFICATION",
                    "NFC",
                    "LIVENESS",
                    "FACEMATCH",
                    "PROOF_OF_ADDRESS",
                    "PHONE",
                    "EMAIL",
                    "AML",
                    "LOCATION",
                    "DATABASE_VALIDATION",
                    "QUESTIONNAIRE",
                    "DOCUMENT_AI",
                    "KYB_REGISTRY",
                    "KYB_DOCUMENTS",
                    "KYB_KEY_PEOPLE",
                    "GEOLOCATION",
                    "SIGNATURE"
                  ],
                  "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Au sein d'un filtrage AML, il s'agit généralement de `AML`, mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                },
                "risk": {
                  "type": "string"
                },
                "additional_data": {
                  "type": "object",
                  "nullable": true
                },
                "log_type": {
                  "type": "string"
                },
                "short_description": {
                  "type": "string"
                },
                "long_description": {
                  "type": "string"
                },
                "node_id": {
                  "type": "string",
                  "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                }
              }
            }
          }
        }
      },
      "MonitoringEvent": {
        "type": "object",
        "description": "Un événement de surveillance enregistré tel que renvoyé par les endpoints de liste et de chronologie du sujet. Les éléments de preuve restreints (payload, contexte de l'appareil, preuves de règle) ne sont renvoyés que par `GET /v3/events/{event_uuid}/`.",
        "required": [
          "event_uuid",
          "event_id",
          "event_category",
          "action_type",
          "occurred_at",
          "received_at",
          "status",
          "score",
          "subject_vendor_data",
          "subject_entity_type",
          "subject_uuid",
          "counterparty_vendor_data",
          "session_id",
          "device_fingerprint",
          "ip_address",
          "ip_country",
          "amount",
          "currency",
          "game_id",
          "round_id",
          "bonus_id",
          "affiliate_code",
          "payment_reference_id",
          "retention_class",
          "rules_matched_count",
          "correlation_pending",
          "is_droppable"
        ],
        "properties": {
          "event_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant Didit de l'événement. Utilisez-le comme `{event_uuid}` dans les appels de récupération et de suppression."
          },
          "event_id": {
            "type": "string",
            "maxLength": 128,
            "description": "Votre propre identifiant, la clé d'idempotence que vous avez envoyée."
          },
          "event_category": {
            "type": "string",
            "enum": [
              "auth",
              "session",
              "gameplay",
              "bonus",
              "affiliate",
              "payment",
              "dispute",
              "security",
              "responsible_gambling",
              "custom"
            ],
            "description": "Catégorie d'événement."
          },
          "action_type": {
            "type": "string",
            "maxLength": 128,
            "description": "Ce qui s'est passé au sein de la catégorie, tel que vous l'avez envoyé."
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure de l'événement de votre côté."
          },
          "received_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles Didit a accepté l'événement."
          },
          "status": {
            "type": "string",
            "enum": [
              "ACCEPTED",
              "APPROVED",
              "IN_REVIEW",
              "DECLINED"
            ],
            "description": "`ACCEPTED` : enregistré, aucune règle correspondante n'a modifié son statut (la réponse normale pour la plupart des événements, et systématiquement la réponse dans une application sandbox, où aucune règle n'est exécutée). `APPROVED` : une règle s'est appliquée et le score est resté sous votre seuil d'examen. `IN_REVIEW` : une règle a fait dépasser le seuil d'examen au score ou a défini le statut. `DECLINED` : une règle l'a refusé ou le score a dépassé votre seuil de refus."
          },
          "score": {
            "type": "integer",
            "description": "Score de règle cumulé. Commence à 0 ; les actions de règle `add_score` le modifient (les deltas négatifs sont autorisés)."
          },
          "subject_vendor_data": {
            "type": "string",
            "maxLength": 255,
            "description": "`subject.vendor_data` de l'événement : votre identifiant pour l'utilisateur ou l'entreprise."
          },
          "subject_entity_type": {
            "type": "string",
            "description": "`individual` ou `company` : le type de sujet désigné par `subject_vendor_data`.",
            "example": "individual"
          },
          "subject_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "UUID de l'utilisateur (particulier) ou de l'entreprise auquel l'événement a été rattaché, ou null lorsque cet enregistrement n'existe plus."
          },
          "counterparty_vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "L'autre acteur d'un événement P2P (promu depuis `payload.counterparty_vendor_data`).",
            "maxLength": 255
          },
          "session_id": {
            "type": "string",
            "nullable": true,
            "description": "`session.session_id` envoyé avec l'événement.",
            "maxLength": 255
          },
          "device_fingerprint": {
            "type": "string",
            "nullable": true,
            "description": "`device_context.fingerprint` envoyé avec l'événement.",
            "maxLength": 255
          },
          "ip_address": {
            "type": "string",
            "nullable": true,
            "description": "Adresse de l'événement. Sur le canal serveur, il s'agit de `device_context.network_context.ip_address` tel que vous l'avez envoyé ; sur le canal appareil, il s'agit de l'IP de la requête.",
            "maxLength": 64
          },
          "ip_country": {
            "type": "string",
            "nullable": true,
            "description": "Code pays de `ip_address` issu de l'enrichissement IP, ou null lorsque l'adresse n'a pas été enrichie (manquante, privée ou télémétrie de faible valeur dont l'adresse n'était pas déjà connue).",
            "example": "ES"
          },
          "amount": {
            "type": "string",
            "nullable": true,
            "description": "Montant sous forme de chaîne décimale avec 18 décimales, provenant de `transaction_context.amount`, `payload.amount` ou `payload.stake_amount`, dans cet ordre.",
            "example": "250.000000000000000000"
          },
          "currency": {
            "type": "string",
            "nullable": true,
            "description": "Devise issue de `transaction_context.currency` ou `payload.currency`.",
            "maxLength": 10
          },
          "game_id": {
            "type": "string",
            "nullable": true,
            "description": "Promu depuis `payload.game_id`.",
            "maxLength": 128
          },
          "round_id": {
            "type": "string",
            "nullable": true,
            "description": "Promu depuis `payload.round_id`.",
            "maxLength": 128
          },
          "bonus_id": {
            "type": "string",
            "nullable": true,
            "description": "Promu depuis `payload.bonus_id`.",
            "maxLength": 128
          },
          "affiliate_code": {
            "type": "string",
            "nullable": true,
            "description": "Promu depuis `payload.affiliate_code`.",
            "maxLength": 128
          },
          "payment_reference_id": {
            "type": "string",
            "nullable": true,
            "description": "Référence de paiement issue de `transaction_context.payment_reference_id` ou de `payload.payment_reference_id`.",
            "maxLength": 255
          },
          "retention_class": {
            "type": "string",
            "enum": [
              "low_value",
              "standard",
              "risk_relevant",
              "monetary_or_compliance"
            ],
            "description": "Classe de conservation. Les événements de paiement et de litige sont `monetary_or_compliance` ; les événements de sécurité et de jeu responsable sont `risk_relevant` ; `session.page_view`, `session.sdk_heartbeat`, `session.sdk_loaded`, `session.device_seen`, `session.bot_signal_observed`, `bonus.promotion_viewed` et `affiliate.referral_clicked` sont `low_value` ; tout le reste est `standard`. Un événement auquel correspond une règle active est promu en `risk_relevant` (jamais rétrogradé)."
          },
          "rules_matched_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Nombre de règles correspondant à l'événement, y compris les règles en mode `TEST` (qui enregistrent des éléments probants sans appliquer d'actions)."
          },
          "correlation_pending": {
            "type": "boolean",
            "description": "`true` tant qu'une règle asynchrone (corrélation entre sujets ou séquence de plus de 24 heures) doit encore s'exécuter pour cet événement. Elle se résout en quelques minutes et `status`, `score` ainsi que `rules_matched_count` se mettent à jour sur place."
          },
          "is_droppable": {
            "type": "boolean",
            "description": "Indique si un SDK soumis à une contre-pression peut abandonner les événements de ce type. `false` pour chaque événement `security`, `payment`, `dispute` et `responsible_gambling`, ainsi que pour `gameplay.bet_placed`, `gameplay.bet_settled` et `gameplay.p2p_settlement`."
          }
        }
      },
      "MonitoringEventDetail": {
        "description": "Un événement de surveillance avec son enveloppe complète, son enrichissement et les éléments de preuve des règles. Chaque champ de `MonitoringEvent` ainsi que les champs ci-dessous.",
        "allOf": [
          {
            "$ref": "#/components/schemas/MonitoringEvent"
          },
          {
            "type": "object",
            "required": [
              "payload",
              "custom_values",
              "device_context",
              "field_sources",
              "session_sequence",
              "table_id",
              "hand_id",
              "match_id",
              "market_id",
              "side",
              "role",
              "net_result_amount",
              "payment_fingerprint",
              "instrument_reference_hash",
              "withdrawal_address_hash",
              "dispute_id",
              "chargeback_id",
              "changed_field",
              "identity_match_ref",
              "schema_version",
              "expires_at",
              "rules_evaluated_count",
              "rule_runs",
              "ip_enrichment",
              "subject_profile",
              "tags"
            ],
            "properties": {
              "payload": {
                "type": "object",
                "additionalProperties": true,
                "description": "Les champs de catégorie que vous avez envoyés dans `payload`."
              },
              "custom_values": {
                "type": "object",
                "additionalProperties": true,
                "description": "Les `custom_values` scalaires que vous avez envoyées. Didit ajoute `vpn_or_proxy_detected: true` ou `is_data_center: true` lorsque l'enrichissement IP signale l'adresse et que vous ne les avez pas définies."
              },
              "device_context": {
                "type": "object",
                "additionalProperties": true,
                "description": "Le contexte de l'appareil tel qu'il est stocké : votre `device_context` (incluant `fingerprint`, `persistent_device_id` et `bot_score` lorsqu'ils sont envoyés) avec `network_context` complété par l'enrichissement IP (`ip_country`, `ip_country_code`, `ip_city`, `asn_number`, `asn_organization`, `is_vpn_or_tor`, `is_data_center`, `proxy_type`, `connection_type`) pour les clés laissées vides."
              },
              "field_sources": {
                "type": "object",
                "additionalProperties": {
                  "type": "string",
                  "enum": [
                    "customer",
                    "sdk",
                    "server"
                  ]
                },
                "description": "Chemin du champ vers sa provenance : `customer` (envoyé par votre backend), `sdk` (envoyé via le canal de l'appareil) ou `server` (dérivé par Didit, comme `received_at` et les champs réseau enrichis). Vérifiez-le avant d'agir sur une correspondance."
              },
              "session_sequence": {
                "type": "integer",
                "format": "int64",
                "nullable": true,
                "description": "`session.sequence` envoyé avec l'événement."
              },
              "table_id": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.table_id`.",
                "maxLength": 128
              },
              "hand_id": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.hand_id`.",
                "maxLength": 128
              },
              "match_id": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.match_id`.",
                "maxLength": 128
              },
              "market_id": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.market_id`.",
                "maxLength": 128
              },
              "side": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.side`.",
                "maxLength": 64
              },
              "role": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.role`.",
                "maxLength": 64
              },
              "net_result_amount": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.net_result_amount`, sous forme de chaîne décimale avec 18 décimales.",
                "example": "-120.000000000000000000"
              },
              "payment_fingerprint": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.payment_fingerprint`.",
                "maxLength": 255
              },
              "instrument_reference_hash": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.instrument_reference_hash`.",
                "maxLength": 255
              },
              "withdrawal_address_hash": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.withdrawal_address_hash` (ou `payload.destination_reference_hash`).",
                "maxLength": 255
              },
              "dispute_id": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.dispute_id`.",
                "maxLength": 255
              },
              "chargeback_id": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.chargeback_id`.",
                "maxLength": 255
              },
              "changed_field": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.changed_field` (événements de changement de sécurité).",
                "maxLength": 128
              },
              "identity_match_ref": {
                "type": "string",
                "nullable": true,
                "description": "Promu depuis `payload.identity_match_ref` (correspondances au registre du jeu responsable).",
                "maxLength": 255
              },
              "schema_version": {
                "type": "integer",
                "description": "Version du schéma de l'enveloppe d'événement. Actuellement `1`.",
                "example": 1
              },
              "expires_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure auxquelles l'événement expire selon sa classe de conservation et est supprimé : `occurred_at` plus la période de la classe (14, 30 ou 90 jours par défaut, ajustable par application). Null pour les événements `monetary_or_compliance`, qui suivent la conservation des transactions."
              },
              "rules_evaluated_count": {
                "type": "integer",
                "minimum": 0,
                "description": "Nombre de règles d'événement évaluées pour cet événement."
              },
              "rule_runs": {
                "type": "array",
                "description": "Chaque règle qui correspondait à l'événement, de la plus récente à la plus ancienne.",
                "items": {
                  "$ref": "#/components/schemas/MonitoringEventRuleRun"
                }
              },
              "ip_enrichment": {
                "type": "object",
                "nullable": true,
                "description": "Enrichissement de l'adresse IP de l'événement, ou null lorsque l'adresse n'a pas été enrichie. Voir [Enrichissement IP](https://docs.didit.me/fr/transaction-monitoring/ip-enrichment).",
                "properties": {
                  "ip_country_code": {
                    "type": "string",
                    "nullable": true,
                    "description": "Code pays de l'adresse."
                  },
                  "ip_city": {
                    "type": "string",
                    "nullable": true,
                    "description": "Ville de l'adresse."
                  },
                  "asn_number": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Numéro de système autonome."
                  },
                  "asn_organization": {
                    "type": "string",
                    "nullable": true,
                    "description": "Organisation qui exploite le système autonome."
                  },
                  "is_vpn_or_tor": {
                    "type": "boolean",
                    "description": "Indique si l'adresse est un nœud de sortie connu d'un VPN ou de Tor."
                  },
                  "is_data_center": {
                    "type": "boolean",
                    "description": "Indique si l'adresse appartient à un réseau d'hébergement ou de centre de données."
                  },
                  "proxy_type": {
                    "type": "string",
                    "nullable": true,
                    "description": "Classification du proxy de l'adresse sous forme de chaîne opaque, ou null."
                  },
                  "last_enriched_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true,
                    "description": "Date et heure du dernier enrichissement de l'adresse."
                  }
                },
                "required": [
                  "ip_country_code",
                  "ip_city",
                  "asn_number",
                  "asn_organization",
                  "is_vpn_or_tor",
                  "is_data_center",
                  "proxy_type",
                  "last_enriched_at"
                ]
              },
              "subject_profile": {
                "type": "object",
                "nullable": true,
                "description": "Signaux de risque d'e-mail et de téléphone en cache pour le sujet, ou null lorsqu'aucun profil n'existe pour le sujet.",
                "properties": {
                  "email_risk_score": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Score de risque de l'e-mail."
                  },
                  "email_deliverability": {
                    "type": "string",
                    "nullable": true,
                    "description": "Verdict de délivrabilité de l'e-mail."
                  },
                  "email_is_disposable": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Indique si l'adresse e-mail est jetable."
                  },
                  "email_is_breached": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Indique si l'adresse e-mail apparaît dans des fuites de données connues."
                  },
                  "email_social_count": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Nombre de comptes en ligne liés à l'adresse e-mail."
                  },
                  "email_social_providers": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Noms des services en ligne où un compte associé à l'adresse e-mail a été trouvé."
                  },
                  "phone_risk_score": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Score de risque téléphonique."
                  },
                  "phone_line_type": {
                    "type": "string",
                    "nullable": true,
                    "description": "Type de ligne téléphonique."
                  },
                  "phone_carrier": {
                    "type": "string",
                    "nullable": true,
                    "description": "Nom de l'opérateur téléphonique."
                  },
                  "phone_social_count": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Nombre de comptes en ligne liés au numéro de téléphone."
                  },
                  "phone_social_providers": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Noms des services en ligne où un compte associé au numéro de téléphone a été trouvé."
                  },
                  "source_provider": {
                    "type": "string",
                    "nullable": true,
                    "description": "Identifiant opaque de la source du profil."
                  },
                  "last_enriched_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true,
                    "description": "Moment où le profil a été actualisé pour la dernière fois."
                  }
                },
                "required": [
                  "email_risk_score",
                  "email_deliverability",
                  "email_is_disposable",
                  "email_is_breached",
                  "email_social_count",
                  "email_social_providers",
                  "phone_risk_score",
                  "phone_line_type",
                  "phone_carrier",
                  "phone_social_count",
                  "phone_social_providers",
                  "source_provider",
                  "last_enriched_at"
                ]
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Noms des tags associés à l'événement (actions de règle `add_tags`)."
              }
            }
          }
        ]
      },
      "MonitoringEventRuleRun": {
        "type": "object",
        "properties": {
          "rule_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID de la règle de surveillance des transactions."
          },
          "rule_title": {
            "type": "string",
            "description": "Titre de la règle."
          },
          "library_key": {
            "type": "string",
            "nullable": true,
            "description": "Clé de bibliothèque lorsque la règle a été installée depuis la bibliothèque de règles, sinon null."
          },
          "matched": {
            "type": "boolean",
            "description": "Toujours `true` : seules les exécutions avec correspondance sont enregistrées."
          },
          "mode": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "TEST"
            ],
            "description": "Mode de la règle lors de son exécution. Une exécution `TEST` enregistre les éléments de preuve mais n'applique aucune action."
          },
          "is_async": {
            "type": "boolean",
            "description": "`true` lorsque l'exécution provient de la passe de corrélation asynchrone plutôt que de la requête d'ingestion."
          },
          "severity": {
            "type": "string",
            "nullable": true,
            "enum": [
              "UNKNOWN",
              "LOW",
              "MEDIUM",
              "HIGH",
              "CRITICAL",
              null
            ],
            "description": "Gravité de la règle. Null pour les exécutions de `TEST` et pour les règles sans gravité."
          },
          "score_delta": {
            "type": "integer",
            "description": "Mesure dans laquelle cette exécution a modifié le score de l'événement (0 pour les exécutions `TEST`)."
          },
          "action_summary": {
            "type": "string",
            "nullable": true,
            "description": "Bref récapitulatif des actions appliquées, par exemple `score +40; add_tag:VPN_LOGIN`. Null lorsque rien n'a été appliqué."
          },
          "matched_payload": {
            "type": "array",
            "description": "Les conditions et agrégations qui ont correspondu. Les entrées de condition comportent `field`, `operator`, `expected_value`, `current_value`, `matched`, `group_index`, `group_logic` et `field_source` (`server`, `sdk` ou `customer`) ; les entrées d'agrégation comportent `metric`, `field`, `operator`, `expected_value`, `computed_value`, `window`, `filters`, `matched` et `sample_references`.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où l'exécution de la règle a été enregistrée."
          }
        },
        "required": [
          "rule_uuid",
          "rule_title",
          "library_key",
          "matched",
          "mode",
          "is_async",
          "severity",
          "score_delta",
          "action_summary",
          "matched_payload",
          "created_at"
        ]
      },
      "MonitoringEventPage": {
        "type": "object",
        "description": "Une page d'événements de surveillance, avec le `occurred_at` le plus récent en premier.",
        "required": [
          "count",
          "next",
          "previous",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "description": "Nombre d'événements correspondants, exact jusqu'à 100 et plafonné à 100 au-delà. Ne calculez pas le nombre de pages à partir de celui-ci ; suivez `next` jusqu'à ce qu'il soit null."
          },
          "next": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL de la page suivante, ou null sur la dernière page."
          },
          "previous": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL de la page précédente, ou null sur la première page."
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MonitoringEvent"
            }
          }
        }
      },
      "MonitoringEventCreateRequest": {
        "type": "object",
        "description": "L'enveloppe de l'événement, identique pour chaque catégorie. Les alias en camelCase sont acceptés : `eventId`, `eventCategory` (ou `category`), `actionType`, `occurredAt`, `timeZone` (ou `zoneId`), `deviceContext` (ou `device`), `transactionContext`, `customValues` (ou `props`) ; dans `subject` : `vendorData`, `entityType`, `fullName` ; dans `session` : `sessionId`, `pageUrl` ; dans `transaction_context` : `paymentReferenceId`.",
        "required": [
          "event_id",
          "event_category",
          "action_type",
          "occurred_at",
          "subject"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "maxLength": 128,
            "description": "Votre identifiant pour l'événement, unique par application. Il s'agit de la clé d'idempotence : renvoyer les mêmes `event_category`, `action_type`, `occurred_at`, `subject.vendor_data` et `payload` sous cet identifiant constitue un rejeu, toute modification constitue un conflit.",
            "example": "login-2026-10-17-000001"
          },
          "event_category": {
            "type": "string",
            "enum": [
              "auth",
              "session",
              "gameplay",
              "bonus",
              "affiliate",
              "payment",
              "dispute",
              "security",
              "responsible_gambling",
              "custom"
            ],
            "description": "Catégorie d'événement.",
            "example": "auth"
          },
          "action_type": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Ce qui s'est passé au sein de la catégorie. Vocabulaire ouvert ; les actions gérées listées dans [Event ingestion](https://docs.didit.me/fr/transaction-monitoring/events) (par exemple `login`, `deposit_completed`, `chargeback_opened`) débloquent la validation typée et les champs de règles gérées. Les espaces de début et de fin sont supprimés.",
            "example": "login"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure de l'événement de votre côté, ISO 8601 (une valeur sans fuseau horaire est lue comme UTC). Ne doit pas dater de plus de 7 jours dans le passé ni dépasser 5 minutes dans le futur.",
            "example": "2026-10-17T09:15:02.481Z"
          },
          "time_zone": {
            "type": "string",
            "nullable": true,
            "maxLength": 64,
            "description": "Fuseau horaire de l'occurrence de votre côté, par exemple `Europe/Madrid`. Enregistré avec l'événement ; non renvoyé par les endpoints de lecture."
          },
          "subject": {
            "type": "object",
            "description": "L'utilisateur ou l'entreprise auquel appartient l'événement. Il correspond à l'utilisateur (ou l'entreprise) ayant ce `vendor_data` dans votre application ; un utilisateur ou une entreprise est créé(e) lorsqu'il n'en existe aucun(e).",
            "required": [
              "vendor_data"
            ],
            "properties": {
              "vendor_data": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "Votre identifiant pour le sujet.",
                "example": "user-42"
              },
              "entity_type": {
                "type": "string",
                "maxLength": 32,
                "default": "individual",
                "description": "`company` associe le sujet à une entreprise ; toute autre valeur (`individual` par défaut) l'associe à un individu. Un même `vendor_data` peut désigner une entreprise et un individu.",
                "example": "individual"
              },
              "full_name": {
                "type": "string",
                "nullable": true,
                "maxLength": 512,
                "description": "Nom d'affichage, utilisé uniquement lorsque cet événement crée l'utilisateur ou l'entreprise."
              },
              "email": {
                "type": "string",
                "format": "email",
                "nullable": true,
                "description": "Validé comme adresse e-mail ; non stocké sur l'événement."
              },
              "phone": {
                "type": "string",
                "nullable": true,
                "maxLength": 32,
                "description": "Validé ; non stocké sur l'événement."
              },
              "country": {
                "type": "string",
                "nullable": true,
                "maxLength": 3,
                "description": "Validé ; non stocké sur l'événement."
              }
            }
          },
          "business": {
            "type": "object",
            "description": "L'entreprise à laquelle appartient l'événement, lorsqu'elle diffère du sujet. Seul `vendor_data` est lu.",
            "additionalProperties": true,
            "properties": {
              "vendor_data": {
                "type": "string",
                "maxLength": 255,
                "description": "Votre identifiant pour l'entreprise. Filtrable via `business_vendor_data`.",
                "example": "merchant-7"
              }
            }
          },
          "session": {
            "type": "object",
            "description": "Le contexte de votre session pour l'événement.",
            "properties": {
              "session_id": {
                "type": "string",
                "nullable": true,
                "maxLength": 255,
                "description": "Votre identifiant de session. Filtrable et renvoyé sous la forme `session_id`."
              },
              "sequence": {
                "type": "integer",
                "nullable": true,
                "description": "Position de l'événement au sein de la session. Renvoyée sous `session_sequence`."
              },
              "page_url": {
                "type": "string",
                "nullable": true,
                "maxLength": 2048,
                "description": "Validé ; non stocké sur l'événement."
              },
              "referrer": {
                "type": "string",
                "nullable": true,
                "maxLength": 2048,
                "description": "Validé ; non stocké sur l'événement."
              }
            }
          },
          "device_context": {
            "type": "object",
            "additionalProperties": true,
            "description": "Contexte de l'appareil et du réseau, stocké tel quel et renvoyé par `GET /v3/events/{event_uuid}/`. Sur cette voie serveur, Didit ne voit pas la connexion de l'utilisateur final ; l'IP enrichie et utilisée par les règles est donc `network_context.ip_address` telle que vous l'envoyez.",
            "properties": {
              "fingerprint": {
                "type": "string",
                "maxLength": 255,
                "description": "Empreinte de l'appareil. Filtrable via `device_fingerprint`."
              },
              "persistent_device_id": {
                "type": "string",
                "maxLength": 255,
                "description": "Votre identifiant d'appareil persistant."
              },
              "bot_score": {
                "type": "integer",
                "description": "Score de bot issu de votre propre détection, sous forme d'entier."
              },
              "network_context": {
                "type": "object",
                "additionalProperties": true,
                "properties": {
                  "ip_address": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Adresse IP de l'utilisateur final. Les adresses publiques sont enrichies une fois par adresse unique.",
                    "example": "203.0.113.42"
                  }
                }
              }
            }
          },
          "transaction_context": {
            "type": "object",
            "description": "Contexte monétaire. Les valeurs non vides ici satisfont également les clés de payload requises de l'action.",
            "properties": {
              "amount": {
                "type": "string",
                "nullable": true,
                "description": "Montant sous forme de chaîne décimale (un nombre est également accepté).",
                "example": "1000.00"
              },
              "currency": {
                "type": "string",
                "nullable": true,
                "maxLength": 10,
                "description": "Code devise."
              },
              "direction": {
                "type": "string",
                "nullable": true,
                "maxLength": 16,
                "description": "Direction du mouvement de fonds, par exemple `inbound` ou `outbound`."
              },
              "payment_reference_id": {
                "type": "string",
                "nullable": true,
                "maxLength": 255,
                "description": "Votre référence de paiement. Filtrable via `payment_reference_id`."
              }
            }
          },
          "payload": {
            "type": "object",
            "additionalProperties": true,
            "description": "Les champs de domaine de la catégorie, au maximum 16384 octets une fois encodés en JSON. Certaines actions requièrent des clés (dans `payload` ou `transaction_context`) : `gameplay.p2p_settlement` nécessite `game_id`, `counterparty_vendor_data`, `stake_amount`, `net_result_amount`, `role` et l'un des champs `hand_id`, `round_id`, `match_id` ; `gameplay.bet_placed` et `gameplay.bet_settled` nécessitent `game_id` ; `payment.deposit_initiated`, `payment.deposit_completed`, `payment.withdrawal_requested` et `payment.withdrawal_completed` nécessitent `payment_reference_id`, `amount`, `currency`, `payment_method`, `status` ; `payment.withdrawal_address_changed` nécessite `withdrawal_address_hash` ; `dispute.chargeback_opened`, `dispute.chargeback_won` et `dispute.chargeback_lost` nécessitent `payment_reference_id` et l'un des champs `dispute_id`, `chargeback_id` ; `session.bot_signal_observed` nécessite `telemetry_schema_version` et l'un des champs `bot_score`, `actions_per_minute`, `timing_variance_ms`, `pointer_entropy`, `keystroke_entropy`, `reaction_time_ms_p50` ; `responsible_gambling.self_exclusion_match` nécessite `registry_source`, `exclusion_status`, `identity_match_ref`. Chaque action `security` se terminant par `_changed` nécessite `changed_field`, ainsi que `previous_reference_hash` ou `new_reference_hash` lorsque le champ est `password`, `mfa_method`, `mfa`, `email`, `phone`, `withdrawal_address`, `payout_method` ou `api_key`. Envoyez des hachages et des références, jamais un numéro de carte, une adresse de retrait complète, un hachage de mot de passe ou un secret MFA."
          },
          "custom_values": {
            "type": "object",
            "description": "Jusqu'à 100 clés personnalisées, adressables depuis les règles sous la forme `custom_values.<key>`. Les valeurs doivent être des scalaires (chaîne, nombre, booléen ou null) ; les objets imbriqués et les tableaux sont rejetés.",
            "additionalProperties": {
              "nullable": true,
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ]
            }
          }
        },
        "example": {
          "event_id": "login-2026-10-17-000001",
          "event_category": "auth",
          "action_type": "login",
          "occurred_at": "2026-10-17T09:15:02.481Z",
          "time_zone": "Europe/Madrid",
          "subject": {
            "vendor_data": "user-42",
            "entity_type": "individual"
          },
          "session": {
            "session_id": "web-session-abc",
            "sequence": 142
          },
          "device_context": {
            "fingerprint": "fp-a8c1",
            "network_context": {
              "ip_address": "203.0.113.42"
            }
          },
          "payload": {
            "method": "password"
          },
          "custom_values": {
            "vip_tier": "gold"
          }
        }
      },
      "MonitoringEventIngestResult": {
        "type": "object",
        "description": "Résultat de l'ingestion d'un événement. Le même format est renvoyé pour un nouvel événement et pour un rejeu idempotent.",
        "required": [
          "event_uuid",
          "event_id",
          "status",
          "score",
          "rules_evaluated_count",
          "rules_matched_count",
          "correlation_pending",
          "retention_class",
          "expires_at",
          "idempotent_replay",
          "rule_matches"
        ],
        "properties": {
          "event_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant Didit de l'événement stocké."
          },
          "event_id": {
            "type": "string",
            "description": "Votre `event_id`."
          },
          "status": {
            "type": "string",
            "enum": [
              "ACCEPTED",
              "APPROVED",
              "IN_REVIEW",
              "DECLINED"
            ],
            "description": "Statut après l'exécution des règles en temps réel. Voir `MonitoringEvent.status`."
          },
          "score": {
            "type": "integer",
            "description": "Score après l'exécution des règles en temps réel."
          },
          "rules_evaluated_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Nombre de règles d'événement évaluées dans la requête. 0 dans une application sandbox, où aucune règle n'est exécutée."
          },
          "rules_matched_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Nombre de règles correspondantes, y compris les règles en mode `TEST`."
          },
          "correlation_pending": {
            "type": "boolean",
            "description": "`true` lorsqu'une règle asynchrone doit encore s'exécuter. Consultez `GET /v3/events/{event_uuid}/` quelques minutes plus tard pour obtenir le `status` et le `score` finaux."
          },
          "retention_class": {
            "type": "string",
            "enum": [
              "low_value",
              "standard",
              "risk_relevant",
              "monetary_or_compliance"
            ],
            "description": "Classe de conservation, après toute promotion par une règle correspondante."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles l'événement expire selon sa classe de conservation et est supprimé. Null pour les événements `monetary_or_compliance` (paiement et litige)."
          },
          "idempotent_replay": {
            "type": "boolean",
            "description": "`true` lorsqu'un événement avec cet `event_id` et le même contenu a déjà été enregistré ; les valeurs sont celles de l'événement stocké et aucune règle n'a été réexécutée."
          },
          "rule_matches": {
            "type": "array",
            "description": "Règles ayant correspondu à l'événement.",
            "items": {
              "type": "object",
              "required": [
                "rule_id",
                "library_key",
                "mode",
                "is_async"
              ],
              "properties": {
                "rule_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "UUID de la règle."
                },
                "library_key": {
                  "type": "string",
                  "nullable": true,
                  "description": "Clé de bibliothèque lorsque la règle a été installée depuis la bibliothèque de règles, sinon null."
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "ACTIVE",
                    "TEST"
                  ],
                  "description": "Les règles `TEST` enregistrent la correspondance mais n'appliquent aucune action."
                },
                "is_async": {
                  "type": "boolean",
                  "description": "`true` lorsque la correspondance provient de la passe asynchrone."
                }
              }
            }
          }
        }
      },
      "ComplianceList": {
        "type": "object",
        "description": "Une liste de blocage, une liste d'autorisation ou une liste personnalisée d'une application.",
        "required": [
          "uuid",
          "name",
          "description",
          "list_type",
          "entry_type",
          "is_system",
          "entry_count",
          "last_entry_added_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de liste. Utilisez-le comme `list_uuid` dans les endpoints de liste et d'entrée, et comme valeur d'une condition de règle de workflow ou de transaction avec `value_type: \"list\"`."
          },
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Nom de la liste, unique parmi les listes de l'application."
          },
          "description": {
            "type": "string",
            "description": "Description en texte libre. Chaîne vide lorsqu'elle n'est pas définie."
          },
          "list_type": {
            "type": "string",
            "enum": [
              "blocklist",
              "allowlist",
              "custom"
            ],
            "description": "`blocklist` : une correspondance refuse la session ou la transaction (listes système uniquement, une par type d'entrée). `allowlist` : les éléments correspondants sont considérés comme fiables, par exemple une liste d'autorisation de visages ignore l'action de visage dupliqué ; ne prévaut jamais sur une correspondance de liste de blocage. `custom` : utilisé dans les conditions de règles de transaction et de workflow (`value_type: \"list\"`)."
          },
          "entry_type": {
            "type": "string",
            "enum": [
              "face",
              "document",
              "phone",
              "email",
              "ip_address",
              "device_fingerprint",
              "wallet_address",
              "bank_account",
              "country",
              "user",
              "business",
              "key"
            ],
            "description": "Ce que contient la liste : `face`, `document` (numéro de document), `phone`, `email`, `ip_address` (adresse ou plage CIDR), `device_fingerprint`, `wallet_address`, `bank_account`, `country` (ISO 3166-1 alpha-3), `user` ou `business` (vos `vendor_data`), ou `key` (toute chaîne). Cela détermine la manière dont les valeurs des entrées sont validées et mises en correspondance."
          },
          "is_system": {
            "type": "boolean",
            "description": "`true` pour les listes configurées par Didit : une liste de blocage par type d'entrée (`face`, `document`, `phone`, `email`, `ip_address`, `device_fingerprint`, `wallet_address`, `bank_account`, `user`, `business`), la liste personnalisée **High Risk Countries** et les listes d'autorisation du système. Les listes système ne peuvent être ni renommées, ni modifiées, ni supprimées ; vous pouvez ajouter et supprimer leurs entrées."
          },
          "entry_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Nombre d'entrées actuellement dans la liste."
          },
          "last_entry_added_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où l'entrée actuelle la plus récente a été ajoutée. `null` pour une liste vide."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où la liste a été créée."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où la liste a été mise à jour pour la dernière fois."
          }
        }
      },
      "ComplianceListEntry": {
        "type": "object",
        "description": "Une valeur dans une liste.",
        "required": [
          "uuid",
          "value",
          "display_label",
          "comment",
          "added_by",
          "reference_session_id",
          "reference_session_number",
          "reference_session_type",
          "reference_object_uuid",
          "metadata",
          "created_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant d'entrée. Utilisez-le comme `entry_uuid` dans Supprimer une entrée de liste."
          },
          "value": {
            "type": "string",
            "description": "La valeur répertoriée : un numéro de téléphone au format E.164, une adresse e-mail, un numéro de document, une adresse IP ou une plage CIDR, une empreinte d'appareil, une adresse, un compte bancaire, un code pays ISO 3166-1 alpha-3, une `vendor_data`, toute chaîne de caractères sur une liste de type `key`, ou l'UUID du visage enregistré sur une liste de visages. Les valeurs que vous envoyez sont stockées en minuscules, à l'exception des numéros de téléphone et des codes pays. La recherche de correspondance est insensible à la casse."
          },
          "display_label": {
            "type": "string",
            "nullable": true,
            "maxLength": 512,
            "description": "Libellé lisible par l'humain. Didit le renseigne pour les entrées issues d'une session (par exemple le nom du titulaire et le numéro de document) lorsque vous n'en transmettez aucun."
          },
          "comment": {
            "type": "string",
            "description": "Note en texte libre. Chaîne vide lorsqu'elle n'est pas définie."
          },
          "added_by": {
            "type": "string",
            "nullable": true,
            "description": "Qui a ajouté l'entrée : `api` (une clé API), l'adresse e-mail d'un utilisateur de la console ou `console`, `system` ou `migration` (entrées créées par Didit), ou `rule` (une action de règle de transaction ou de surveillance)."
          },
          "reference_session_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Session de vérification dont provient l'entrée. `null` lorsque l'entrée a été ajoutée par valeur."
          },
          "reference_session_number": {
            "type": "integer",
            "nullable": true,
            "description": "Numéro de cette session propre à l'application, tel qu'affiché dans la console."
          },
          "reference_session_type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "kyc",
              "kyb",
              null
            ],
            "description": "`kyc` pour une session de vérification de personne, `kyb` pour une session de vérification d'entreprise, `null` lorsqu'il n'y a pas de session."
          },
          "reference_object_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "L'enregistrement que l'entrée représente : l'enregistrement de visage, de document, de téléphone ou d'e-mail lu à partir d'une session, le visage créé par Charger un visage dans une liste, ou l'UUID que vous avez envoyé (par exemple un UUID de transaction ou le `didit_internal_id` d'un utilisateur)."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Contexte supplémentaire. Contient les clés définies par Didit (listées ici) fusionnées avec les `metadata` que vous avez envoyées lors de la création de l'entrée, renvoyées telles quelles. `null` lorsqu'il n'y en a pas.",
            "properties": {
              "reference_image_url": {
                "type": "string",
                "description": "Entrées faciales : URL signée à courte durée de vie, réémise à chaque appel ; `null` pour une clé API restreinte sans `media: read`. Absent lorsqu'aucune image n'est associée à l'entrée."
              },
              "front_image_url": {
                "type": "string",
                "description": "Entrées de documents comportant une image du recto du document : URL signée de courte durée, réémise à chaque appel ; `null` pour une clé API restreinte sans `media: read`."
              },
              "full_name": {
                "type": "string",
                "description": "Entrées de documents issues d'une session : nom complet du titulaire."
              },
              "issuing_state": {
                "type": "string",
                "description": "Entrées de documents issues d'une session : pays de délivrance ISO 3166-1 alpha-3."
              },
              "document_type": {
                "type": "string",
                "description": "Entrées de documents issues d'une session : code du type de document, par exemple `P`, `ID` ou `DL`."
              },
              "region": {
                "type": "string",
                "description": "Entrées de documents issues d'une session : État ou province de délivrance pour un document émis au niveau régional, vide si non applicable. Non défini par l'ajout d'éléments de session à la liste de blocage."
              },
              "document_number": {
                "type": "string",
                "description": "Entrées de documents issues d'une session : numéro du document."
              },
              "face_image_source": {
                "type": "string",
                "enum": [
                  "front_image_camera_front",
                  "back_image_camera_front"
                ],
                "description": "Entrées faciales issues d'un selfie de capture de document : identifiant du selfie. Absent pour les visages de détection du vivant."
              },
              "reference_node_id": {
                "type": "string",
                "nullable": true,
                "description": "Entrées faciales issues d'un selfie de capture de document : le nœud de Vérification d'identité dont provient le selfie."
              },
              "fingerprint_tier": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "persistent_id",
                  "composite_hash",
                  "legacy_fp",
                  "unknown",
                  null
                ],
                "description": "Entrées d'empreinte d'appareil provenant d'une session : mode de dérivation de l'empreinte. `persistent_id` identifie un appareil ; `composite_hash` et `legacy_fp` peuvent être partagés par des appareils du même modèle."
              },
              "sandbox": {
                "type": "boolean",
                "description": "`true` pour une entrée faciale téléversée dans une application sandbox ; une telle entrée ne correspond à aucun élément."
              },
              "reference_type": {
                "type": "string",
                "enum": [
                  "transaction",
                  "vendor_user",
                  "vendor_business"
                ],
                "description": "Défini par vous : élément vers lequel pointe `reference_object_uuid`, afin que la console puisse créer un lien vers celui-ci."
              },
              "reference_id": {
                "type": "string",
                "description": "Défini par vous : identifiant de l'enregistrement source."
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure d'ajout de l'entrée."
          }
        }
      },
      "BlocklistedItem": {
        "type": "object",
        "description": "Un visage, un document d'identité, un numéro de téléphone ou une adresse e-mail sur liste de blocage provenant d'une session de vérification. Les champs qui ne s'appliquent pas au `type` de l'élément sont `null`.",
        "required": [
          "type",
          "session_id",
          "session_number",
          "blocklisted_at",
          "face_image",
          "document_type",
          "document_number",
          "front_image",
          "phone_number",
          "country_code",
          "email"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "face",
              "document",
              "phone",
              "email"
            ],
            "description": "Ce qui a été ajouté à la liste de blocage."
          },
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "Session de vérification à laquelle appartient l'élément."
          },
          "session_number": {
            "type": "integer",
            "nullable": true,
            "description": "Numéro de cette session propre à l'application, tel qu'affiché dans la console."
          },
          "blocklisted_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où l'élément a été ajouté à la liste de blocage pour la dernière fois."
          },
          "face_image": {
            "type": "string",
            "nullable": true,
            "description": "Éléments faciaux : URL signée à courte durée de vie, réémise à chaque appel ; `null` pour une clé API restreinte sans `media: read`. Également `null` lorsqu'aucune image de référence n'est stockée."
          },
          "document_type": {
            "type": "string",
            "nullable": true,
            "description": "Éléments de document : code du type de document, par exemple `P` (passeport), `ID` (carte nationale d'identité), `DL` (permis de conduire) ou `RP` (titre de séjour)."
          },
          "document_number": {
            "type": "string",
            "nullable": true,
            "description": "Éléments de document : numéro du document, ou numéro personnel lorsque le document n'en comporte pas."
          },
          "front_image": {
            "type": "string",
            "nullable": true,
            "description": "Éléments de document : image du recto du document, URL signée de courte durée, réémise à chaque appel ; `null` pour une clé API restreinte sans `media: read`."
          },
          "phone_number": {
            "type": "string",
            "nullable": true,
            "description": "Éléments téléphoniques : le numéro de téléphone au format E.164."
          },
          "country_code": {
            "type": "string",
            "nullable": true,
            "description": "Éléments téléphoniques : pays ISO 3166-1 alpha-2 du numéro."
          },
          "email": {
            "type": "string",
            "nullable": true,
            "description": "Éléments de l'e-mail : l'adresse e-mail."
          }
        }
      },
      "TransactionNote": {
        "type": "object",
        "description": "Une note dans la chronologie d'examen d'une transaction surveillée.",
        "required": [
          "uuid",
          "note",
          "actor_email",
          "actor_name",
          "metadata",
          "created_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de la note."
          },
          "note": {
            "type": "string",
            "description": "Corps de la note en texte brut."
          },
          "actor_email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "description": "E-mail de l'utilisateur de la Console ayant rédigé la note ou modifié le statut. `null` pour les notes créées avec une clé API et pour les notes ajoutées automatiquement par Didit."
          },
          "actor_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom d'affichage de l'utilisateur de la Console (son e-mail lorsqu'il n'a pas de nom). `Rule Engine` pour les notes ajoutées automatiquement par Didit. `null` pour les notes créées avec une clé API."
          },
          "metadata": {
            "type": "object",
            "description": "Distingue les types de notes. Les notes rédigées via l'API ou la Console contiennent `mentioned_emails`. Un changement de statut effectué dans la Console contient `type: status_change` avec `previous_status`, `new_status`, `reason_code` et `reason_label`. Les notes ajoutées par Didit contiennent `source` : `rule_action` (avec `rule_uuid`) pour l'action `add_note` d'une règle, ou `remediation_session` pour un problème de création de la session de vérification d'action utilisateur.",
            "properties": {
              "mentioned_emails": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "email"
                },
                "description": "Membres de l'organisation mentionnés, en minuscules et dédupliqués. Vide si personne n'a été mentionné."
              },
              "type": {
                "type": "string",
                "enum": [
                  "status_change"
                ],
                "description": "Présent sur les notes enregistrant un changement de statut effectué dans la Console."
              },
              "previous_status": {
                "type": "string",
                "enum": [
                  "APPROVED",
                  "IN_REVIEW",
                  "DECLINED",
                  "AWAITING_USER"
                ],
                "description": "Statut avant la modification."
              },
              "new_status": {
                "type": "string",
                "enum": [
                  "APPROVED",
                  "IN_REVIEW",
                  "DECLINED",
                  "AWAITING_USER"
                ],
                "description": "Statut après la modification."
              },
              "reason_code": {
                "type": "string",
                "nullable": true,
                "description": "Code du motif indiqué lors de la modification."
              },
              "reason_label": {
                "type": "string",
                "nullable": true,
                "description": "Libellé du motif indiqué lors de la modification."
              },
              "source": {
                "type": "string",
                "enum": [
                  "rule_action",
                  "remediation_session"
                ],
                "description": "Présent sur les notes ajoutées automatiquement par Didit."
              },
              "rule_uuid": {
                "type": "string",
                "format": "uuid",
                "description": "Règle dont l'action `add_note` a rédigé la note (avec `source: rule_action`)."
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où la note a été enregistrée."
          }
        }
      },
      "TransactionSummary": {
        "type": "object",
        "description": "Résumé d'une transaction surveillée, au format indiqué par `GET /v3/transactions/`. Appelez `GET /v3/transactions/{transaction_id}/` avec `uuid` pour obtenir les parties, alertes et exécutions de règles.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID de transaction Didit. Utilisez-le comme `{transaction_id}` sur les endpoints de transaction."
          },
          "transaction_number": {
            "type": "integer",
            "nullable": true,
            "description": "Numéro séquentiel propre à l'application affiché dans la console."
          },
          "txn_id": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre identifiant issu de l'appel de création. Unique par application."
          },
          "transaction_type": {
            "type": "string",
            "description": "Catégorie telle qu'enregistrée : `finance`, `kyc`, `travelRule`, `userPlatformEvent`, `gamblingBet`, `gamblingLimitChange`, `gamblingBonusChange` ou `auditTrailEvent`."
          },
          "action_type": {
            "type": "string",
            "description": "Sous-type au sein de la catégorie, par exemple `withdrawal`."
          },
          "status": {
            "type": "string",
            "enum": [
              "APPROVED",
              "IN_REVIEW",
              "DECLINED",
              "AWAITING_USER"
            ],
            "description": "Verdict actuel de la surveillance."
          },
          "source": {
            "type": "string",
            "enum": [
              "LIVE",
              "IMPORTED"
            ],
            "description": "`LIVE` pour les transactions soumises à la surveillance, `IMPORTED` pour les imports historiques."
          },
          "direction": {
            "type": "string",
            "enum": [
              "INBOUND",
              "OUTBOUND"
            ],
            "description": "Direction par rapport au sujet."
          },
          "amount": {
            "type": "string",
            "description": "Montant sous forme de chaîne décimale avec les zéros finaux supprimés (jusqu'à 18 décimales)."
          },
          "currency": {
            "type": "string",
            "description": "Code devise ou symbole d'actif crypto de `amount`."
          },
          "currency_type": {
            "type": "string",
            "nullable": true,
            "description": "`fiat` ou `crypto` lorsque cette information est connue."
          },
          "preferred_currency_amount": {
            "type": "string",
            "nullable": true,
            "description": "`amount` converti dans la devise préférée de l'application, lorsqu'un taux était disponible."
          },
          "preferred_currency_code": {
            "type": "string",
            "nullable": true,
            "description": "Devise de `preferred_currency_amount`."
          },
          "payment_details": {
            "type": "string",
            "nullable": true,
            "description": "Référence de paiement en texte libre."
          },
          "txn_date": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles la transaction a eu lieu."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles Didit l'a enregistré."
          },
          "score": {
            "type": "integer",
            "description": "Score de risque. Plus il est élevé, plus le risque est grand."
          },
          "severity": {
            "type": "string",
            "nullable": true,
            "enum": [
              "UNKNOWN",
              "LOW",
              "MEDIUM",
              "HIGH",
              "CRITICAL",
              null
            ],
            "description": "Gravité du risque, `null` jusqu'à ce qu'un élément la définisse."
          },
          "decision_reason_code": {
            "type": "string",
            "nullable": true,
            "description": "Raison lisible par machine pour le `status` actuel."
          },
          "decision_reason_label": {
            "type": "string",
            "nullable": true,
            "description": "Libellé lisible par l'humain pour `decision_reason_code`."
          },
          "tags": {
            "type": "array",
            "description": "Tags sur la transaction.",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "color": {
                  "type": "string",
                  "description": "Couleur hexadécimale, par exemple `#F59E0B`."
                },
                "description": {
                  "type": "string",
                  "nullable": true
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "didit",
                    "custom"
                  ],
                  "description": "Tag prédéfini ou personnalisé Didit."
                }
              }
            }
          },
          "subject_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom complet de la partie `APPLICANT`."
          },
          "subject_vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre `vendor_data` pour le candidat."
          },
          "subject_type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "user",
              "business",
              null
            ],
            "description": "Indique si le candidat est lié à un utilisateur ou à une entreprise Didit ; `null` lorsqu'il n'est lié à aucun des deux."
          },
          "subject_uuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "UUID de l'utilisateur ou de l'entreprise Didit auquel le candidat est lié."
          },
          "subject_country": {
            "type": "string",
            "nullable": true,
            "description": "Code pays du demandeur."
          },
          "counterparty_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom complet de la partie `COUNTERPARTY`, le cas échéant."
          },
          "counterparty_vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre `vendor_data` pour la contrepartie."
          },
          "counterparty_country": {
            "type": "string",
            "nullable": true,
            "description": "Code pays de la contrepartie."
          },
          "assigned_to_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom du réviseur de la Console assigné à la transaction."
          },
          "travel_rule_status": {
            "type": "string",
            "nullable": true,
            "description": "Statut du transfert Travel Rule de la transaction, ou `null` lorsqu'il n'en a aucun."
          },
          "application_id": {
            "type": "string",
            "format": "uuid",
            "description": "Application à laquelle appartient la transaction."
          },
          "application_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de cette application."
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "description": "Organisation propriétaire de l'application."
          },
          "organization_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de cette organisation."
          }
        }
      },
      "ApplicationAnalyticsDataPoint": {
        "type": "object",
        "description": "Nombre de sessions pour un jour donné, par date de création (UTC). Chaque décompte reflète le statut actuel de la session. Les points de la période précédente comportent au moins les champs obligatoires.",
        "required": [
          "rounded_date",
          "total",
          "approved",
          "declined",
          "canceled",
          "pending"
        ],
        "properties": {
          "rounded_date": {
            "type": "string",
            "format": "date",
            "description": "Le jour, `YYYY-MM-DD`."
          },
          "total": {
            "type": "integer",
            "description": "Sessions créées ce jour-là."
          },
          "approved": {
            "type": "integer",
            "description": "Parmi celles-ci, les sessions `Approved` ou `Kyc Expired`."
          },
          "declined": {
            "type": "integer",
            "description": "Sessions `Declined`."
          },
          "canceled": {
            "type": "integer",
            "description": "Sessions `Expired` ou `Abandoned`."
          },
          "pending": {
            "type": "integer",
            "description": "Sessions `Not Started`, `In Progress` ou `In Review`."
          },
          "in_review": {
            "type": "integer",
            "description": "Sessions `In Review`."
          },
          "expired": {
            "type": "integer",
            "description": "Sessions `Expired`."
          },
          "abandoned": {
            "type": "integer",
            "description": "Sessions `Abandoned`."
          },
          "in_progress": {
            "type": "integer",
            "description": "Sessions `In Progress`."
          },
          "not_started": {
            "type": "integer",
            "description": "Sessions `Not Started`."
          },
          "manually_approved": {
            "type": "integer",
            "description": "Sessions approuvées par un réviseur après qu'un autre verdict a été rendu par le workflow."
          },
          "manually_declined": {
            "type": "integer",
            "description": "Sessions refusées par un réviseur après qu'un autre verdict a été rendu par le workflow."
          }
        }
      },
      "ApplicationAnalyticsRequestBreakdown": {
        "type": "object",
        "description": "Totaux de statuts pour la période. La répartition de la période précédente contient au moins les champs requis.",
        "required": [
          "total_approved",
          "total_in_review",
          "total_declined",
          "total_canceled",
          "total_pending"
        ],
        "properties": {
          "total_approved": {
            "type": "integer",
            "description": "Sessions `Approved` ou `Kyc Expired`."
          },
          "total_in_review": {
            "type": "integer",
            "description": "Sessions `In Review`."
          },
          "total_declined": {
            "type": "integer",
            "description": "Sessions `Declined`."
          },
          "total_canceled": {
            "type": "integer",
            "description": "Sessions `Expired` ou `Abandoned`."
          },
          "total_pending": {
            "type": "integer",
            "description": "Sessions `Not Started`, `In Progress` ou `In Review` (inclut `total_in_review`)."
          },
          "total_expired": {
            "type": "integer",
            "description": "Sessions `Expired`."
          },
          "total_abandoned": {
            "type": "integer",
            "description": "Sessions `Abandoned`."
          },
          "total_in_progress": {
            "type": "integer",
            "description": "Sessions `In Progress`."
          },
          "total_not_started": {
            "type": "integer",
            "description": "Sessions `Not Started`."
          },
          "total_manually_approved": {
            "type": "integer",
            "description": "Approuvé par un réviseur."
          },
          "total_manually_declined": {
            "type": "integer",
            "description": "Refusé par un réviseur."
          }
        }
      },
      "ApplicationAnalyticsCountryCount": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "description": "Nom du pays."
          },
          "country_code": {
            "type": "string",
            "description": "Code pays à deux lettres."
          },
          "session_count": {
            "type": "integer",
            "description": "Sessions provenant de ce pays."
          }
        }
      },
      "ApplicationAnalyticsLocationStats": {
        "type": "object",
        "properties": {
          "ip_countries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsCountryCount"
            },
            "description": "Pays des adresses IP des utilisateurs, classés par nombre de sessions décroissant."
          },
          "countries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsCountryCount"
            },
            "description": "Même liste que `ip_countries`."
          },
          "id_countries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsCountryCount"
            },
            "description": "Pays de délivrance des documents d'identité vérifiés, par nombre décroissant de sessions."
          },
          "conversion_by_country": {
            "type": "array",
            "description": "Par pays de délivrance du document : sessions terminées (approuvé, refusé ou en cours d'examen) et nombre de sessions approuvées. Les pays comptant le plus de sessions terminées en premier.",
            "items": {
              "type": "object",
              "properties": {
                "country": {
                  "type": "string"
                },
                "country_code": {
                  "type": "string"
                },
                "finished": {
                  "type": "integer"
                },
                "approved": {
                  "type": "integer"
                }
              }
            }
          },
          "cities": {
            "type": "array",
            "description": "Jusqu'à 100 villes d'IP, les villes comptant le plus de sessions en premier.",
            "items": {
              "type": "object",
              "properties": {
                "location": {
                  "type": "string",
                  "description": "`City, Country`."
                },
                "session_count": {
                  "type": "integer"
                },
                "latitude": {
                  "type": "number",
                  "nullable": true
                },
                "longitude": {
                  "type": "number",
                  "nullable": true
                }
              }
            }
          }
        }
      },
      "ApplicationAnalyticsDemographicStats": {
        "type": "object",
        "properties": {
          "age_distribution": {
            "type": "object",
            "description": "Sessions par tranche d'âge issues de la pièce d'identité. Vide lorsqu'il n'y a pas de données.",
            "properties": {
              "under_18": {
                "type": "integer"
              },
              "18_24": {
                "type": "integer"
              },
              "25_34": {
                "type": "integer"
              },
              "35_44": {
                "type": "integer"
              },
              "45_64": {
                "type": "integer"
              },
              "65_plus": {
                "type": "integer"
              }
            },
            "additionalProperties": {
              "type": "integer"
            }
          },
          "gender_distribution": {
            "type": "object",
            "description": "Sessions par code de genre du document : `M`, `F` ou `U` (inconnu).",
            "additionalProperties": {
              "type": "integer"
            }
          }
        }
      },
      "ApplicationAnalyticsDeviceDetails": {
        "type": "object",
        "description": "Les cinq premiers de chaque catégorie, avec les sessions les plus nombreuses en premier.",
        "properties": {
          "device_models": {
            "type": "array",
            "description": "Marques d'appareils : `Apple`, `Android`, `LG`, tout le reste étant regroupé sous `Other`.",
            "items": {
              "type": "object",
              "properties": {
                "device": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "browsers": {
            "type": "array",
            "description": "Navigateurs : `Chrome`, `Safari`, `Didit App`, `Firefox`, tout le reste étant regroupé sous `Other`.",
            "items": {
              "type": "object",
              "properties": {
                "browser": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "operating_systems": {
            "type": "array",
            "description": "Systèmes d'exploitation.",
            "items": {
              "type": "object",
              "properties": {
                "os": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "ApplicationAnalyticsWorkflowFunnel": {
        "type": "object",
        "description": "Indexé par ID de workflow. `total` correspond aux sessions démarrées sur ce workflow ; `steps` compte les sessions ayant atteint chaque étape (`OCR`, `LIVENESS`, `FACE_MATCH`, `AML`, `POA`, `PHONE`, `EMAIL`, `NFC`, `DATABASE_VALIDATION`, `QUESTIONNAIRE`, `IP_ANALYSIS`, `AGE_ESTIMATION`, `KYB_REGISTRY`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE`). Atteindre une étape ne signifie pas la valider.",
        "additionalProperties": {
          "type": "object",
          "properties": {
            "total": {
              "type": "integer"
            },
            "steps": {
              "type": "object",
              "additionalProperties": {
                "type": "object",
                "properties": {
                  "reached": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      },
      "ApplicationAnalyticsVerificationTimeStats": {
        "type": "object",
        "description": "Temps actif passé par les utilisateurs à se vérifier, sans compter les périodes d'inactivité. Objet vide en l'absence de données.",
        "properties": {
          "overall_avg_seconds": {
            "type": "number",
            "description": "Moyenne par session, une décimale."
          },
          "overall_count": {
            "type": "integer",
            "description": "Sessions mesurées."
          },
          "per_feature": {
            "type": "object",
            "description": "Indexé par fonctionnalité, par exemple `OCR` ou `LIVENESS`.",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "avg_seconds": {
                  "type": "number"
                },
                "total_seconds": {
                  "type": "number"
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "per_sub_step": {
            "type": "object",
            "description": "Indexé par fonctionnalité, puis par sous-étape, par exemple `front_id_photo`.",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": {
                "type": "object",
                "properties": {
                  "avg_seconds": {
                    "type": "number"
                  },
                  "total_seconds": {
                    "type": "number"
                  },
                  "count": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      },
      "ApplicationAnalyticsResubmissionStats": {
        "type": "object",
        "properties": {
          "first_pass": {
            "type": "integer",
            "description": "Sessions terminées sans nouvelle soumission."
          },
          "second": {
            "type": "integer",
            "description": "Sessions terminées soumises à nouveau une fois."
          },
          "third_plus": {
            "type": "integer",
            "description": "Sessions terminées soumises à nouveau deux fois ou plus."
          },
          "abandoned": {
            "type": "integer",
            "description": "Sessions abandonnées."
          }
        }
      },
      "ApplicationAnalyticsOriginalStatusStats": {
        "type": "object",
        "description": "Le verdict automatique du workflow, avant toute modification par un réviseur.",
        "properties": {
          "approved": {
            "type": "integer"
          },
          "in_review": {
            "type": "integer"
          },
          "declined": {
            "type": "integer"
          }
        }
      },
      "ApplicationAnalyticsWarningStats": {
        "type": "object",
        "description": "Indexé par fonctionnalité (`ID_VERIFICATION`, `LIVENESS`, `FACEMATCH`, `AML`, `PROOF_OF_ADDRESS`, `PHONE`, `EMAIL`, `NFC`, `LOCATION`, `DATABASE_VALIDATION`, `QUESTIONNAIRE` et les fonctionnalités KYB). `total` correspond aux sessions ayant atteint la fonctionnalité ; `risks` compte les sessions par code et niveau d'avertissement.",
        "additionalProperties": {
          "type": "object",
          "properties": {
            "total": {
              "type": "integer"
            },
            "risks": {
              "type": "object",
              "additionalProperties": {
                "type": "object",
                "properties": {
                  "error": {
                    "type": "integer"
                  },
                  "warning": {
                    "type": "integer"
                  },
                  "information": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      },
      "ApplicationAnalyticsDemographicPoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Clé de période : `YYYY-MM-DD` pour un jour, le lundi d'une semaine, ou `YYYY-MM` pour un mois, selon `grouping_mode`."
          },
          "age_distribution": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "gender_distribution": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          }
        }
      },
      "ApplicationAnalyticsDevicePoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Clé de période : `YYYY-MM-DD` pour un jour, le lundi d'une semaine, ou `YYYY-MM` pour un mois, selon `grouping_mode`."
          },
          "devices": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "browsers": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "operating_systems": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          }
        }
      },
      "ApplicationAnalyticsVerificationTimePoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Clé de période : `YYYY-MM-DD` pour un jour, le lundi d'une semaine, ou `YYYY-MM` pour un mois, selon `grouping_mode`."
          },
          "overall_avg": {
            "type": "number",
            "description": "Secondes actives moyennes par session."
          },
          "per_feature": {
            "type": "object",
            "description": "Secondes actives moyennes par fonctionnalité.",
            "additionalProperties": {
              "type": "number"
            }
          }
        }
      },
      "ApplicationAnalyticsResubmissionPoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Clé de période : `YYYY-MM-DD` pour un jour, le lundi d'une semaine, ou `YYYY-MM` pour un mois, selon `grouping_mode`."
          },
          "first_pass": {
            "type": "integer"
          },
          "second": {
            "type": "integer"
          },
          "third_plus": {
            "type": "integer"
          },
          "abandoned": {
            "type": "integer"
          }
        }
      },
      "ApplicationAnalyticsOriginalStatusPoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Clé de période : `YYYY-MM-DD` pour un jour, le lundi d'une semaine, ou `YYYY-MM` pour un mois, selon `grouping_mode`."
          },
          "approved": {
            "type": "integer"
          },
          "in_review": {
            "type": "integer"
          },
          "declined": {
            "type": "integer"
          }
        }
      },
      "ApplicationAnalyticsSummary": {
        "type": "object",
        "description": "Résumé de la vérification d'identité (KYC) de l'utilisateur, renvoyé lorsque ni `scope` ni `widget_keys` ne sont envoyés.",
        "required": [
          "data_points",
          "request_breakdown",
          "previous_data_points",
          "previous_request_breakdown",
          "conversion_rate",
          "location_stats",
          "demographic_stats",
          "device_details",
          "workflow_funnel_stats",
          "verification_time_stats",
          "resubmission_stats",
          "warning_stats",
          "original_status_stats",
          "grouping_mode",
          "demographic_time_series",
          "device_time_series",
          "verification_time_time_series",
          "resubmission_time_series",
          "original_status_time_series"
        ],
        "properties": {
          "data_points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsDataPoint"
            },
            "description": "Un point par jour, du premier jour avec des sessions dans l'intervalle jusqu'à `end_date`. Toujours quotidien, quelle que soit la valeur de `grouping_mode`."
          },
          "request_breakdown": {
            "$ref": "#/components/schemas/ApplicationAnalyticsRequestBreakdown"
          },
          "previous_data_points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsDataPoint"
            },
            "description": "Points quotidiens pour la période de même durée précédant immédiatement `start_date`."
          },
          "previous_request_breakdown": {
            "$ref": "#/components/schemas/ApplicationAnalyticsRequestBreakdown"
          },
          "conversion_rate": {
            "type": "number",
            "nullable": true,
            "description": "`total_approved / (total_approved + total_declined + total_in_review) x 100`, une décimale. `null` lorsque rien n'est terminé."
          },
          "location_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsLocationStats"
          },
          "demographic_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsDemographicStats"
          },
          "device_details": {
            "$ref": "#/components/schemas/ApplicationAnalyticsDeviceDetails"
          },
          "workflow_funnel_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsWorkflowFunnel"
          },
          "verification_time_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsVerificationTimeStats"
          },
          "resubmission_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsResubmissionStats"
          },
          "warning_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsWarningStats"
          },
          "original_status_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsOriginalStatusStats"
          },
          "grouping_mode": {
            "type": "string",
            "enum": [
              "day",
              "week",
              "month"
            ],
            "description": "Manière dont les listes `*_time_series` sont regroupées : `day` jusqu'à 14 jours, `week` jusqu'à 90, `month` au-delà. Mesuré à partir du premier jour comportant des sessions dans la plage."
          },
          "demographic_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsDemographicPoint"
            }
          },
          "device_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsDevicePoint"
            }
          },
          "verification_time_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsVerificationTimePoint"
            }
          },
          "resubmission_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsResubmissionPoint"
            }
          },
          "original_status_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsOriginalStatusPoint"
            }
          }
        }
      },
      "ApplicationAnalyticsWidget": {
        "type": "object",
        "description": "Un widget de tableau de bord. Chaque widget possède `kind` et `title` ; les autres champs dépendent de `kind`. Les widgets de session réutilisent les objets récapitulatifs (`data_points`, `request_breakdown`, `workflow_funnel_stats`, etc.) ; les widgets de liste placent leurs entrées dans `items` ; les métriques de transaction utilisent `value`.",
        "required": [
          "kind",
          "title"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "sessions_volume",
              "workflow_funnel",
              "average_verification_time",
              "country_distribution",
              "warning_insights",
              "conversion_rate",
              "conversion_by_country",
              "resubmission_insights",
              "original_status_distribution",
              "database_validation_coverage",
              "database_validation_latency",
              "demographics",
              "device_details",
              "horizontal_bar",
              "kyb_registry_coverage",
              "kyb_registry_data_completeness",
              "metric",
              "time_series",
              "breakdown",
              "status_time_series",
              "leaderboard",
              "histogram"
            ],
            "description": "Type de widget."
          },
          "title": {
            "type": "string",
            "description": "Titre d'affichage, par exemple `Verification volume`."
          },
          "grouping_mode": {
            "type": "string",
            "enum": [
              "day",
              "week",
              "month"
            ],
            "description": "Manière dont les listes `*_time_series` sont regroupées : `day` jusqu'à 14 jours, `week` jusqu'à 90, `month` au-delà. Mesuré à partir du premier jour comportant des sessions dans la plage."
          },
          "data_points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsDataPoint"
            }
          },
          "request_breakdown": {
            "$ref": "#/components/schemas/ApplicationAnalyticsRequestBreakdown"
          },
          "previous_data_points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsDataPoint"
            }
          },
          "previous_request_breakdown": {
            "$ref": "#/components/schemas/ApplicationAnalyticsRequestBreakdown"
          },
          "conversion_rate": {
            "type": "number",
            "nullable": true
          },
          "workflow_funnel_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsWorkflowFunnel"
          },
          "verification_time_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsVerificationTimeStats"
          },
          "verification_time_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsVerificationTimePoint"
            }
          },
          "warning_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsWarningStats"
          },
          "resubmission_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsResubmissionStats"
          },
          "resubmission_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsResubmissionPoint"
            }
          },
          "original_status_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsOriginalStatusStats"
          },
          "original_status_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsOriginalStatusPoint"
            }
          },
          "demographic_stats": {
            "$ref": "#/components/schemas/ApplicationAnalyticsDemographicStats"
          },
          "demographic_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsDemographicPoint"
            }
          },
          "device_details": {
            "$ref": "#/components/schemas/ApplicationAnalyticsDeviceDetails"
          },
          "device_time_series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationAnalyticsDevicePoint"
            }
          },
          "items": {
            "type": "array",
            "description": "Entrées d'un widget de liste. `country_distribution` (KYC) : `country`, `country_code`, `session_count`. `conversion_by_country` : `country`, `country_code`, `finished`, `approved`. `time_series` : `date`, `value`. `status_time_series` : `date`, `approved`, `declined`, `flagged`. `breakdown` : `transaction_type` ou `action_type` avec `count` et `volume`, ou `tag_id`, `tag_name`, `count`. `leaderboard` : `rule_title`, `trigger_count` ou `assignee`, `handled_count`, `average_processing_seconds`, chacun avec `approved_percentage`, `declined_percentage`, `flagged_percentage`. `histogram` : `score`, `count`.",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "previous_items": {
            "type": "array",
            "description": "Série temporelle des transactions pour la période de même durée précédant immédiatement `start_date`.",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "value": {
            "type": "number",
            "description": "Widgets `metric` : le chiffre pour la période."
          },
          "currency": {
            "type": "string",
            "nullable": true,
            "description": "Widgets de volume et de montant des transactions : devise par défaut des transactions de l'application."
          },
          "thresholds": {
            "type": "object",
            "description": "Widget `histogram` : les seuils de score d'examen et de refus de l'application.",
            "properties": {
              "review": {
                "type": "integer"
              },
              "decline": {
                "type": "integer"
              }
            }
          },
          "search": {
            "type": "object",
            "description": "Widget `kyb_registry_coverage` : totaux de recherche dans les registres.",
            "properties": {
              "searches_total": {
                "type": "integer"
              },
              "searches_with_no_candidates": {
                "type": "integer"
              }
            }
          }
        }
      },
      "ApplicationAnalyticsWidgetResponse": {
        "type": "object",
        "description": "Widgets du tableau de bord, renvoyés lorsque `scope` ou `widget_keys` est envoyé.",
        "required": [
          "scope",
          "available_widget_keys",
          "requested_widget_keys",
          "widgets"
        ],
        "properties": {
          "scope": {
            "type": "string",
            "enum": [
              "home",
              "kyc",
              "kyb",
              "transactions"
            ],
            "description": "Onglet du tableau de bord."
          },
          "available_widget_keys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Chaque clé de widget acceptée par cette portée."
          },
          "requested_widget_keys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Les clés du widget retournées, dans l'ordre : vos `widget_keys` valides, ou les valeurs par défaut du scope."
          },
          "widgets": {
            "type": "object",
            "description": "Indexé par clé de widget, dans l'ordre de `requested_widget_keys`.",
            "additionalProperties": {
              "$ref": "#/components/schemas/ApplicationAnalyticsWidget"
            }
          }
        }
      },
      "ApplicationAnalyticsToday": {
        "type": "object",
        "description": "Vérifications d'aujourd'hui par heure locale par rapport au même jour de la semaine la semaine dernière.",
        "required": [
          "time_zone",
          "date",
          "current_hour",
          "previous_date",
          "hours",
          "previous_hours",
          "total",
          "previous_total_so_far",
          "outcomes"
        ],
        "properties": {
          "time_zone": {
            "type": "string",
            "description": "Le fuseau horaire IANA auquel correspondent le jour et ses heures.",
            "example": "Europe/Madrid"
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "Aujourd'hui dans ce fuseau horaire.",
            "example": "2026-10-30"
          },
          "current_hour": {
            "type": "integer",
            "minimum": 0,
            "maximum": 23,
            "description": "L'heure locale actuelle.",
            "example": 14
          },
          "previous_date": {
            "type": "string",
            "format": "date",
            "description": "Le jour de comparaison : le même jour de la semaine une semaine plus tôt.",
            "example": "2026-10-23"
          },
          "hours": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 0
            },
            "minItems": 24,
            "maxItems": 24,
            "description": "Vérifications créées aujourd'hui, par heure locale à partir de 00:00. Les heures à venir indiquent 0."
          },
          "previous_hours": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 0
            },
            "minItems": 24,
            "maxItems": 24,
            "description": "Vérifications créées le jour de comparaison, par heure locale à partir de 00:00."
          },
          "total": {
            "type": "integer",
            "minimum": 0,
            "description": "Vérifications créées aujourd'hui jusqu'à présent.",
            "example": 165
          },
          "previous_total_so_far": {
            "type": "integer",
            "minimum": 0,
            "description": "Vérifications créées le jour de comparaison jusqu'à la même heure locale.",
            "example": 151
          },
          "outcomes": {
            "type": "object",
            "description": "Parmi les vérifications d'aujourd'hui, combien sont actuellement approuvées, en attente d'examen et refusées. Les autres ne sont pas encore terminées.",
            "required": [
              "approved",
              "in_review",
              "declined"
            ],
            "properties": {
              "approved": {
                "type": "integer",
                "minimum": 0
              },
              "in_review": {
                "type": "integer",
                "minimum": 0
              },
              "declined": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        }
      },
      "WebhookConfigDestination": {
        "type": "object",
        "description": "Une destination de webhook telle que répertoriée dans la configuration des webhooks, sans métriques de livraison. `GET /v3/webhook/destinations/{destination_uuid}/` ajoute son récapitulatif de livraison.",
        "required": [
          "uuid",
          "label",
          "url",
          "enabled",
          "webhook_version",
          "secret_shared_key",
          "subscribed_events",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "ID de destination."
          },
          "label": {
            "type": "string",
            "maxLength": 255,
            "description": "Nom lisible par l'utilisateur."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2000,
            "description": "Endpoint HTTPS auquel Didit envoie les événements."
          },
          "enabled": {
            "type": "boolean",
            "description": "`false` suspend les livraisons vers cette destination."
          },
          "webhook_version": {
            "type": "string",
            "enum": [
              "v1",
              "v2",
              "v3"
            ],
            "description": "Version du payload envoyée à cette destination."
          },
          "secret_shared_key": {
            "type": "string",
            "description": "Le secret de signature de cette destination (token de 43 caractères compatible avec les URL). Vérifiez chaque webhook avec le secret de la destination à laquelle il a été envoyé. Les appelants par clé API le reçoivent toujours dans son intégralité ; les utilisateurs de la console sans `read:webhooks` reçoivent une chaîne vide."
          },
          "subscribed_events": {
            "type": "array",
            "uniqueItems": true,
            "description": "Types d'événements livrés à cette destination. Vide lorsque la destination a été créée sans événements, auquel cas elle ne reçoit rien.",
            "items": {
              "$ref": "#/components/schemas/WebhookEvent"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookConfig": {
        "type": "object",
        "description": "Configuration des webhooks au niveau de l'application, politique de conservation et hôtes de retour de portefeuille Digital ID, avec chaque destination de webhook.",
        "required": [
          "webhook_url",
          "webhook_version",
          "secret_shared_key",
          "capture_method",
          "data_retention_months",
          "face_retention_policy",
          "face_retention_days",
          "available_events",
          "allowed_return_hosts",
          "endpoints"
        ],
        "properties": {
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL de webhook (héritée) au niveau de l'application. Didit n'envoie vers celle-ci que lorsque l'application ne dispose d'aucune destination activée, et uniquement `status.updated` et `data.updated`. Chaque création, mise à jour ou suppression d'une destination la définit sur l'URL de la destination activée la plus ancienne, ou sur `null` lorsqu'aucune n'est activée."
          },
          "webhook_version": {
            "type": "string",
            "enum": [
              "v1",
              "v2",
              "v3"
            ],
            "description": "Version du payload de l'ancien `webhook_url`. Chaque destination possède sa propre `webhook_version`."
          },
          "secret_shared_key": {
            "type": "string",
            "description": "Secret de signature au niveau de l'application (token de 43 caractères compatible URL). Il signe uniquement les livraisons vers la `webhook_url` héritée ; chaque destination signe avec son propre `secret_shared_key`. Les appelants utilisant une clé API le reçoivent toujours dans son intégralité ; les utilisateurs de la console sans `read:webhooks` reçoivent une chaîne vide."
          },
          "capture_method": {
            "type": "string",
            "enum": [
              "MOBILE",
              "MOBILE_AND_DESKTOP"
            ],
            "description": "Paramètre d'application obsolète. Le workflow de vérification ne le lit pas : les options de capture sont configurées par workflow."
          },
          "data_retention_months": {
            "type": "integer",
            "nullable": true,
            "minimum": 1,
            "maximum": 120,
            "description": "Délai de suppression automatique. Les sessions de vérification des utilisateurs créées il y a plus de ce nombre de mois (un mois correspond à 30 jours) sont supprimées automatiquement, et cette suppression est irréversible. `null` signifie que les sessions ne sont jamais supprimées automatiquement. Voir [Conservation des données](https://docs.didit.me/fr/console/data-retention)."
          },
          "face_retention_policy": {
            "type": "string",
            "enum": [
              "delete_with_session",
              "retain_until_user_deleted"
            ],
            "description": "Ce qui advient de l'embedding facial d'une session lorsque la session est supprimée. `delete_with_session` (par défaut) le supprime avec la session. `retain_until_user_deleted` correspond à l'option de [conservation des gabarits biométriques](https://docs.didit.me/fr/console/data-retention#conservation-des-gabarits-biométriques) : un gabarit biométrique sans image lié à l'User est géré séparément jusqu'à ce que sa période de conservation prenne fin, que l'User soit supprimé ou que vous le purgiez."
          },
          "face_retention_days": {
            "type": "integer",
            "nullable": true,
            "minimum": 1,
            "maximum": 3650,
            "description": "Durée de conservation, en jours, des gabarits biométriques sous `retain_until_user_deleted`. Requis lorsque cette politique est définie."
          },
          "biometric_consent_mode": {
            "type": "string",
            "enum": [
              "auto",
              "always",
              "never"
            ],
            "description": "Moment où le flux hébergé et les SDK natifs demandent à la personne son consentement biométrique explicite avant une capture faciale. `auto` (par défaut) ne le demande que lorsqu'un déclencheur s'applique : un État déclaré, l'IP de la personne ou l'émetteur du document d'identité se trouve dans l'Illinois, au Texas ou au Colorado, ou la personne semble être aux États-Unis sans État connu. `always` le demande à chaque personne dont le workflow capture un visage. `never` n'affiche jamais l'étape, et vous recueillez vous-même le consentement avant le selfie. Chaque modification est enregistrée dans le journal d'audit. Voir [Consentement biométrique](https://docs.didit.me/fr/getting-started/biometric-consent)."
          },
          "available_events": {
            "type": "array",
            "description": "Chaque type d'événement auquel une destination peut s'abonner, avec un libellé d'affichage.",
            "items": {
              "type": "object",
              "required": [
                "value",
                "label"
              ],
              "properties": {
                "value": {
                  "$ref": "#/components/schemas/WebhookEvent"
                },
                "label": {
                  "type": "string",
                  "description": "Libellé d'affichage, par exemple `Session status updated`."
                }
              }
            }
          },
          "allowed_return_hosts": {
            "type": "array",
            "maxItems": 20,
            "description": "Noms d'hôte (correspondance exacte, HTTPS uniquement) vers lesquels une vérification de portefeuille Digital ID autonome peut renvoyer l'utilisateur avec son `return_url`. Votre domaine en marque blanche est également toujours autorisé. Voir [Enregistrer votre destination de retour](https://docs.didit.me/fr/standalone-apis/digital-id-wallets#enregistrer-votre-destination-de-retour).",
            "items": {
              "type": "string",
              "maxLength": 253
            }
          },
          "endpoints": {
            "type": "array",
            "description": "Chaque destination de webhook de l'application, de la plus ancienne à la plus récente, chacune avec son secret de signature. En lecture seule ici : gérez les destinations avec les endpoints `/v3/webhook/destinations/`.",
            "items": {
              "$ref": "#/components/schemas/WebhookConfigDestination"
            }
          },
          "allowed_domains": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "maxLength": 300
            },
            "description": "Origines (par exemple `https://app.example.com` ; `http` uniquement pour `localhost`) dans lesquelles le flux de vérification hébergé peut être intégré et vers lesquelles il peut rediriger l'utilisateur avec un rappel de session. Les appels de serveur à serveur ne sont pas affectés. Une liste vide signifie qu'il n'y a aucune restriction. Didit enregistre chaque origine en minuscules sans port par défaut. Une entrée non valide échoue avec une erreur `400` sur `allowed_domains`.",
            "example": [
              "https://app.example.com"
            ]
          }
        }
      },
      "WebhookDestinationDelivery": {
        "type": "object",
        "description": "Une tentative de livraison vers une destination de webhook. Le premier envoi d'un événement, chaque nouvelle tentative automatique et chaque renvoi constituent des livraisons distinctes.",
        "required": [
          "uuid",
          "session_id",
          "request_url",
          "response_status",
          "response_time_ms",
          "status",
          "webhook_type",
          "created_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "ID de livraison, pour les appels de consultation détaillée et de renvoi."
          },
          "session_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Session de vérification d'utilisateur concernée par l'événement. `null` pour les événements de session d'entreprise, ainsi que pour les événements utilisateur, entreprise, de transaction, de Travel Rule et de workflow."
          },
          "request_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL à laquelle la livraison a été envoyée : l'URL de la destination au moment où l'événement a été généré."
          },
          "response_status": {
            "type": "integer",
            "nullable": true,
            "description": "Code d'état HTTP renvoyé par votre endpoint. `null` tant que la livraison est en file d'attente et n'a pas encore été tentée. Lorsqu'aucune réponse HTTP n'a été reçue, Didit enregistre son propre statut : `504` lorsque votre endpoint n'a pas répondu dans un délai de 5 secondes, `503` en cas d'échec de connexion, `400` lorsque l'URL a été rejetée car non sécurisée (par exemple une adresse privée ou interne), et `404` pour toute autre erreur de requête. Un code supérieur ou égal à `400` est considéré comme une livraison échouée."
          },
          "response_time_ms": {
            "type": "integer",
            "nullable": true,
            "minimum": 0,
            "description": "Durée de la tentative, en millisecondes. `null` tant que la livraison est dans la file d'attente."
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Statut signalé par l'événement lors de sa génération : le statut de la session pour les événements de session (par exemple `Approved` ou `In Review`), le statut de la personne ou de l'entreprise pour les événements utilisateur et entreprise, et le statut de la transaction pour les événements de transaction. `null` pour les événements ne comportant aucun statut."
          },
          "webhook_type": {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure de création de la livraison."
          }
        }
      },
      "WebhookDestinationDeliveryDetail": {
        "type": "object",
        "description": "Une tentative de livraison vers une destination de webhook, avec exactement les en-têtes et le corps de requête envoyés par Didit.",
        "required": [
          "uuid",
          "session_id",
          "request_url",
          "response_status",
          "response_time_ms",
          "status",
          "webhook_type",
          "created_at",
          "request_header",
          "request_body"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "ID de livraison, pour les appels de consultation détaillée et de renvoi."
          },
          "session_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Session de vérification d'utilisateur concernée par l'événement. `null` pour les événements de session d'entreprise, ainsi que pour les événements utilisateur, entreprise, de transaction, de Travel Rule et de workflow."
          },
          "request_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL à laquelle la livraison a été envoyée : l'URL de la destination au moment où l'événement a été généré."
          },
          "response_status": {
            "type": "integer",
            "nullable": true,
            "description": "Code d'état HTTP renvoyé par votre endpoint. `null` tant que la livraison est en file d'attente et n'a pas encore été tentée. Lorsqu'aucune réponse HTTP n'a été reçue, Didit enregistre son propre statut : `504` lorsque votre endpoint n'a pas répondu dans un délai de 5 secondes, `503` en cas d'échec de connexion, `400` lorsque l'URL a été rejetée car non sécurisée (par exemple une adresse privée ou interne), et `404` pour toute autre erreur de requête. Un code supérieur ou égal à `400` est considéré comme une livraison échouée."
          },
          "response_time_ms": {
            "type": "integer",
            "nullable": true,
            "minimum": 0,
            "description": "Durée de la tentative, en millisecondes. `null` tant que la livraison est dans la file d'attente."
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Statut signalé par l'événement lors de sa génération : le statut de la session pour les événements de session (par exemple `Approved` ou `In Review`), le statut de la personne ou de l'entreprise pour les événements utilisateur et entreprise, et le statut de la transaction pour les événements de transaction. `null` pour les événements ne comportant aucun statut."
          },
          "webhook_type": {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure de création de la livraison."
          },
          "request_header": {
            "type": "string",
            "description": "Texte JSON (une chaîne de caractères) des en-têtes de requête envoyés par Didit : `Content-Type`, `X-Signature`, `X-Signature-V2`, `X-Signature-Simple`, `X-Timestamp` et `User-Agent`. Analysez-le avec un parseur JSON. Il contient les signatures, jamais le secret de signature."
          },
          "request_body": {
            "type": "string",
            "description": "Texte JSON (une chaîne de caractères) du payload exact envoyé par Didit, clés triées, comprenant `event_id` et `timestamp`. Analysez-le avec un parseur JSON ; voir [Format du payload](https://docs.didit.me/fr/integration/webhooks#structure-du-payload). Pour une clé restreinte sans `media: read`, les URL de médias qu'il contient sont `null` ; sans `sessions: write`, les tokens de session et les liens de vérification hébergés sont `null`. Un corps modifié de cette manière ne correspond plus à ses signatures. Didit n'enregistre pas le corps de réponse renvoyé par votre endpoint."
          }
        }
      },
      "SessionWebhookDelivery": {
        "type": "object",
        "description": "Une tentative de livraison de webhook enregistrée pour une session de vérification, avec les en-têtes et le corps exacts de la requête envoyée par Didit.",
        "required": [
          "uuid",
          "session_id",
          "request_url",
          "response_status",
          "status",
          "webhook_type",
          "request_header",
          "request_body",
          "created_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "ID de livraison. Utilisez-le comme `{webhook_uuid}` pour obtenir ou renvoyer cette livraison."
          },
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "La session à laquelle appartient la livraison (la session indiquée dans le chemin)."
          },
          "request_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL à laquelle la livraison a été envoyée."
          },
          "response_status": {
            "type": "integer",
            "nullable": true,
            "description": "Code d'état HTTP renvoyé par votre endpoint. `null` tant que la livraison est en file d'attente et n'a pas encore été tentée. Lorsqu'aucune réponse HTTP n'a été reçue, Didit enregistre son propre statut : `504` lorsque votre endpoint n'a pas répondu dans un délai de 5 secondes, `503` en cas d'échec de connexion, `400` lorsque l'URL a été rejetée car non sécurisée (par exemple une adresse privée ou interne), et `404` pour toute autre erreur de requête. Un code supérieur ou égal à `400` est considéré comme une livraison échouée."
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Statut de la session lors de la génération de l'événement, par exemple `In Progress`, `Approved` ou `Declined`."
          },
          "webhook_type": {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          "request_header": {
            "type": "string",
            "description": "Texte JSON (une chaîne de caractères) des en-têtes de requête envoyés par Didit : `Content-Type`, `X-Signature`, `X-Signature-V2`, `X-Signature-Simple`, `X-Timestamp` et `User-Agent`. Analysez-le avec un parseur JSON. Il contient les signatures, jamais le secret de signature."
          },
          "request_body": {
            "type": "string",
            "description": "Texte JSON (une chaîne de caractères) du payload exact envoyé par Didit, clés triées, comprenant `event_id` et `timestamp`. Analysez-le avec un parseur JSON ; voir [Format du payload](https://docs.didit.me/fr/integration/webhooks#structure-du-payload). Pour une clé restreinte sans `media: read`, les URL de médias qu'il contient sont `null` ; sans `sessions: write`, les tokens de session et les liens de vérification hébergés sont `null`. Un corps modifié de cette manière ne correspond plus à ses signatures. Didit n'enregistre pas le corps de réponse renvoyé par votre endpoint."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure de création de la livraison."
          }
        }
      },
      "SessionEvent": {
        "type": "object",
        "description": "Une entrée dans la chronologie des événements d'une session de vérification.",
        "required": [
          "uuid",
          "event_type",
          "created_at",
          "component",
          "feature_step",
          "step",
          "details",
          "ip_address",
          "user_agent",
          "device_info",
          "file_url",
          "sent_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de l'événement."
          },
          "event_type": {
            "type": "string",
            "enum": [
              "SESSION_CREATED",
              "SESSION_COMPLETED",
              "SESSION_STATUS_CHANGED",
              "LINK_OPENED",
              "FORM_SUBMITTED",
              "BUTTON_CLICKED",
              "FILE_UPLOADED",
              "ATTEMPT_FAILED",
              "FEATURE_STEP_CHANGED",
              "STEP_RENDERED",
              "NOTE_ADDED",
              "MANUAL_REVIEW_STARTED",
              "WORKFLOW_BRANCH_EVALUATED",
              "WORKFLOW_STATUS_NODE_REACHED",
              "LOG"
            ],
            "description": "Ce qui s'est passé. Signalé par l'appareil pendant le flux hébergé ou le SDK : `LINK_OPENED`, `STEP_RENDERED`, `BUTTON_CLICKED`, `FORM_SUBMITTED`, `FILE_UPLOADED`, `ATTEMPT_FAILED` et `LOG` (débogage). Enregistré par le serveur : `SESSION_CREATED`, `SESSION_STATUS_CHANGED` (`details.old_status`, `details.current_status`), `FEATURE_STEP_CHANGED` (`details.old_feature_step`, `details.current_feature_step`), `WORKFLOW_BRANCH_EVALUATED` et `WORKFLOW_STATUS_NODE_REACHED` (la trace de routage du workflow). `SESSION_COMPLETED`, `NOTE_ADDED` et `MANUAL_REVIEW_STARTED` peuvent apparaître sur les sessions plus anciennes."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles Didit a stocké l'événement. Les événements sont stockés de manière asynchrone, quelques secondes après `sent_at`."
          },
          "component": {
            "type": "string",
            "nullable": true,
            "description": "Composant d'interface utilisateur ayant signalé l'événement (événements de l'appareil uniquement)."
          },
          "feature_step": {
            "type": "string",
            "nullable": true,
            "enum": [
              "OCR",
              "OCR_BACK",
              "NFC",
              "AML",
              "FACE",
              "LIVENESS",
              "FACE_MATCH",
              "IP_ANALYSIS",
              "AGE_ESTIMATION",
              "PROOF_OF_ADDRESS",
              "PHONE_VERIFICATION",
              "EMAIL_VERIFICATION",
              "FACE_SEARCH",
              "DATABASE_VALIDATION",
              "QUESTIONNAIRE",
              "KYB_REGISTRY",
              "KYB_DOCUMENTS",
              "KYB_KEY_PEOPLE",
              "DOCUMENT_AI",
              "GEOLOCATION",
              null
            ],
            "description": "Fonctionnalité de vérification sur laquelle se trouvait la session lorsque l'événement s'est produit."
          },
          "step": {
            "type": "string",
            "nullable": true,
            "description": "Écran au sein de la fonctionnalité, par exemple `DOCUMENT_CAPTURE_FRONT` ou `FACE_PASSIVE_LIVENESS`."
          },
          "details": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Données spécifiques à l'événement. Les clés dépendent de `event_type`."
          },
          "ip_address": {
            "type": "string",
            "nullable": true,
            "description": "Adresse depuis laquelle l'appareil a signalé l'événement. `null` pour les événements enregistrés côté serveur."
          },
          "user_agent": {
            "type": "string",
            "nullable": true,
            "description": "Agent utilisateur de l'appareil. `null` pour les événements enregistrés par le serveur."
          },
          "device_info": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Détails de l'appareil signalés par le SDK ou le navigateur."
          },
          "file_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Lien pré-signé de courte durée vers un fichier joint à l'événement (par exemple une image capturée). `null` lorsqu'il n'y en a pas, et systématiquement `null` pour une clé API restreinte sans `media: read`."
          },
          "sent_at": {
            "type": "integer",
            "format": "int64",
            "description": "Date et heure de l'événement, sous forme de timestamp Unix en millisecondes. Les résultats sont triés selon cette valeur."
          }
        }
      },
      "AMLDatasetSourceFreshness": {
        "type": "object",
        "description": "Fraîcheur d'une famille de jeux de données AML.",
        "required": [
          "last_updated_at",
          "oldest_updated_at",
          "dataset_count",
          "dated_dataset_count"
        ],
        "properties": {
          "last_updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Mise à jour la plus récente de n'importe quel jeu de données de la famille."
          },
          "oldest_updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Limite d'obsolescence : chaque jeu de données de la famille est au moins aussi récent. `null` lorsqu'au moins un jeu de données de la famille n'a indiqué aucune date de mise à jour, car la limite est alors inconnue."
          },
          "dataset_count": {
            "type": "integer",
            "description": "Nombre de jeux de données dans la famille."
          },
          "dated_dataset_count": {
            "type": "integer",
            "description": "Nombre de ces jeux de données ayant signalé une date de mise à jour."
          }
        }
      },
      "AMLDatasetFreshness": {
        "type": "object",
        "description": "Degré de fraîcheur des jeux de données AML lors de l'exécution d'un filtrage. Les dates ne sont jamais estimées.",
        "required": [
          "captured_at",
          "provider",
          "catalog_version",
          "sources"
        ],
        "properties": {
          "captured_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles Didit a lu le catalogue de jeux de données dont provient cette fraîcheur."
          },
          "provider": {
            "type": "string",
            "description": "Identifiant opaque de la source de données AML. Traitez-le comme une chaîne opaque ; ne créez pas de branche conditionnelle dessus.",
            "example": "aml_data_source"
          },
          "catalog_version": {
            "type": "string",
            "nullable": true,
            "description": "Identifiant de version du catalogue de jeux de données, lorsque la source en transmet un."
          },
          "sources": {
            "type": "object",
            "description": "Fraîcheur par famille de jeux de données. Une famille dont les jeux de données n'ont signalé aucune date de mise à jour est absente plutôt que renseignée avec `null`.",
            "properties": {
              "sanctions": {
                "$ref": "#/components/schemas/AMLDatasetSourceFreshness"
              },
              "pep": {
                "$ref": "#/components/schemas/AMLDatasetSourceFreshness"
              },
              "warnings": {
                "$ref": "#/components/schemas/AMLDatasetSourceFreshness"
              },
              "adverse_media": {
                "$ref": "#/components/schemas/AMLDatasetSourceFreshness"
              }
            }
          }
        }
      },
      "AMLScreeningRun": {
        "type": "object",
        "description": "Une revérification terminée d'un contrôle AML dans le cadre de la surveillance continue.",
        "required": [
          "uuid",
          "run_id",
          "completed_at",
          "started_at",
          "outcome",
          "trigger",
          "provider",
          "status",
          "score",
          "total_hits",
          "new_hits",
          "entities_screened",
          "dataset_freshness"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de cette exécution de filtrage."
          },
          "run_id": {
            "type": "string",
            "format": "uuid",
            "description": "L'exécution de surveillance à laquelle appartient ce filtrage. Chaque vérification filtrée lors de la même exécution la partage."
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles le nouveau filtrage de ce sujet s'est terminé. Les résultats sont triés par cette valeur, du plus récent au plus ancien."
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où le lot de surveillance auquel appartient ce nouveau filtrage a débuté."
          },
          "outcome": {
            "type": "string",
            "enum": [
              "NO_CHANGE",
              "CHANGED",
              "FAILED"
            ],
            "description": "`NO_CHANGE` : terminé et le résultat n'a pas changé. `CHANGED` : terminé et le score, le statut, le nombre de correspondances ou les correspondances ont changé. `FAILED` : aucune réponse exploitable pour ce sujet, la vérification a donc été laissée en l'état."
          },
          "trigger": {
            "type": "string",
            "enum": [
              "ONGOING_MONITORING"
            ],
            "description": "Ce qui a déclenché le filtrage. Toujours `ONGOING_MONITORING` actuellement."
          },
          "provider": {
            "type": "string",
            "description": "Identifiant opaque de la source de données AML ayant répondu. Traitez-le comme une chaîne opaque ; ne créez pas de branche conditionnelle dessus.",
            "example": "aml_data_source"
          },
          "status": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Not Finished",
              "Approved",
              "Declined",
              "In Review",
              "Resub Requested",
              null
            ],
            "description": "Statut du contrôle AML à l'issue de cette exécution."
          },
          "score": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "minimum": 0,
            "maximum": 100,
            "description": "Score AML de la vérification à l'issue de cette exécution."
          },
          "total_hits": {
            "type": "integer",
            "nullable": true,
            "description": "Nombre de correspondances que cette exécution a laissées dans la vérification."
          },
          "new_hits": {
            "type": "integer",
            "nullable": true,
            "description": "Nombre de correspondances trouvées par cette exécution que la vérification n'avait pas auparavant. `0` si rien de nouveau n'a été trouvé ; `null` si l'exécution a échoué ou a été enregistrée avant que ce décompte n'existe."
          },
          "entities_screened": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1,
            "description": "Nombre d'entités filtrées par cette exécution pour la vérification : `1` lorsque le sujet a été filtré, `0` lorsque l'exécution a échoué."
          },
          "dataset_freshness": {
            "allOf": [
              {
                "$ref": "#/components/schemas/AMLDatasetFreshness"
              }
            ],
            "nullable": true,
            "description": "Fraîcheur du jeu de données pour cette exécution, ou `null` si aucune date n'était disponible."
          }
        }
      },
      "KYBKeyPeopleParty": {
        "type": "object",
        "description": "Une personne clé d'une session de Vérification d'entreprise (KYB), avec sa vérification enfant. La même partie apparaît dans `key_people_checks[].submitted.parties[]` de la décision de session d'entreprise.",
        "required": [
          "uuid",
          "entity_type",
          "source",
          "name",
          "is_active",
          "is_skipped",
          "requires_verification",
          "roles",
          "kyc_session_deleted",
          "kyb_sub_session_deleted"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de la partie."
          },
          "entity_type": {
            "type": "string",
            "enum": [
              "person",
              "company"
            ],
            "description": "Indique si la partie est un particulier ou une entreprise."
          },
          "source": {
            "type": "string",
            "enum": [
              "REGISTRY",
              "USER"
            ],
            "description": "`REGISTRY` : provient du registre des sociétés. `USER` : saisi dans l'écran Key People."
          },
          "name": {
            "type": "string",
            "description": "Nom d'affichage de la partie."
          },
          "first_name": {
            "type": "string",
            "nullable": true,
            "description": "Prénom (personnes physiques)."
          },
          "last_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de famille (personnes physiques)."
          },
          "company_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de l'entreprise (parties de type entreprise)."
          },
          "registration_number": {
            "type": "string",
            "nullable": true,
            "description": "Numéro d'immatriculation de l'entreprise (parties de type entreprise)."
          },
          "email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "description": "E-mail auquel le lien de vérification est envoyé."
          },
          "nationality": {
            "type": "string",
            "nullable": true,
            "description": "Nationalité pour les personnes physiques, pays de constitution pour les entreprises."
          },
          "phone_number": {
            "type": "string",
            "nullable": true,
            "description": "Numéro de téléphone recueilli pour la partie."
          },
          "date_of_birth": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "Date de naissance (personnes)."
          },
          "position": {
            "type": "string",
            "nullable": true,
            "description": "Intitulé de poste en texte libre (personnes physiques)."
          },
          "custom_fields": {
            "type": "object",
            "additionalProperties": true,
            "description": "Champs personnalisés définis par le workflow collectés pour la partie, indexés par clé de champ."
          },
          "is_active": {
            "type": "boolean",
            "description": "Indique si la partie est active."
          },
          "is_skipped": {
            "type": "boolean",
            "description": "Indique si la partie est exemptée de vérification. Une régénération l'efface."
          },
          "requires_verification": {
            "type": "boolean",
            "description": "Indique si les règles de rôle et d'actionnariat exigent une vérification pour cette partie."
          },
          "roles": {
            "type": "array",
            "description": "Rôles que la partie détient dans l'entreprise.",
            "items": {
              "type": "object",
              "required": [
                "role",
                "ownership_percent",
                "voting_percent"
              ],
              "properties": {
                "role": {
                  "type": "string",
                  "enum": [
                    "director",
                    "non_executive_director",
                    "secretary",
                    "chairman",
                    "ubo",
                    "shareholder",
                    "representative",
                    "founder",
                    "legal_advisor",
                    "authorized_signatory",
                    "trustee",
                    "beneficiary",
                    "settlor",
                    "protector",
                    "company_officer",
                    "investor",
                    "other"
                  ],
                  "description": "Code du rôle."
                },
                "ownership_percent": {
                  "type": "number",
                  "nullable": true,
                  "description": "Pourcentage de détention pour ce rôle, lorsqu'il est connu."
                },
                "voting_percent": {
                  "type": "number",
                  "nullable": true,
                  "description": "Pourcentage de droits de vote pour ce rôle, lorsqu'il est connu."
                }
              }
            }
          },
          "kyc_session_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Session KYC individuelle enfant (personnes)."
          },
          "kyc_session_status": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Not Started",
              "In Progress",
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned",
              "Kyc Expired",
              "Resubmitted",
              "Awaiting User",
              null
            ],
            "description": "Statut de la session KYC enfant. Une session supprimée conserve le statut qu'elle avait au moment de sa suppression."
          },
          "kyc_session_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Lien hébergé de la session KYC enfant. `null` lorsqu'il n'y en a pas ou qu'elle a été supprimée, ainsi que pour une clé API restreinte sans `sessions: write`."
          },
          "kyc_session_deleted": {
            "type": "boolean",
            "description": "La session KYC enfant a été supprimée, elle ne pourra donc jamais aboutir."
          },
          "kyb_sub_session_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Session KYB enfant (parties morales)."
          },
          "kyb_sub_session_status": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Not Started",
              "In Progress",
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned",
              "Kyc Expired",
              "Resubmitted",
              "Awaiting User",
              null
            ],
            "description": "Statut de la session KYB enfant."
          },
          "kyb_sub_session_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Lien hébergé de la session KYB enfant, avec les mêmes règles de valeur `null` que `kyc_session_url`."
          },
          "kyb_sub_session_deleted": {
            "type": "boolean",
            "description": "Équivalent côté entreprise de `kyc_session_deleted`."
          },
          "verification_workflow_type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "kyc",
              "kyb",
              "adaptive_age_verification",
              "biometric_authentication",
              "address_verification",
              "questionnaire_verification",
              "email_verification",
              "phone_verification",
              null
            ],
            "description": "Type de workflow exécuté par la session enfant."
          },
          "verification_workflow_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Workflow exécuté par la session enfant."
          },
          "verification_workflow_label": {
            "type": "string",
            "nullable": true,
            "description": "Libellé de ce workflow."
          },
          "verification_workflow_features": {
            "type": "array",
            "nullable": true,
            "description": "Fonctionnalités du workflow de la session enfant avec leur statut actuel.",
            "items": {
              "type": "object",
              "required": [
                "feature",
                "status"
              ],
              "properties": {
                "feature": {
                  "type": "string",
                  "description": "Code de la fonctionnalité, par exemple `ID_VERIFICATION` ou `LIVENESS`."
                },
                "status": {
                  "type": "string",
                  "description": "Statut de la fonctionnalité, `Not Finished` jusqu'à son exécution."
                }
              }
            }
          },
          "didit_internal_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Identifiant Didit de la personne vérifiée, une fois connue."
          }
        }
      },
      "TravelRuleDelivery": {
        "type": "object",
        "description": "État d'acheminement du dernier message que le transfert doit à l'autre partie. Didit contacte la contrepartie après le retour de la requête ayant créé ou modifié le transfert ; cet objet indique donc si ce message a abouti : en file d'attente, en cours d'envoi, en attente de nouvelle tentative après une erreur, livré ou échoué. Une défaillance dont le réseau peut encore se remettre (absence de réponse dans les délais, échec de connexion, HTTP `408`, `429` ou `5xx`) fait l'objet d'une nouvelle tentative après 30 secondes, 2 minutes, 10 minutes, 30 minutes et 1 heure. Lorsqu'un premier message (`kind: SEND`) échoue définitivement, parce que le réseau l'a refusé ou que la sixième tentative a également échoué, le transfert passe à `COUNTERPARTY_VASP_NOT_REACHABLE` avec `last_error` dans sa `timeline` ; tout autre message échouant définitivement est consigné dans la `timeline`. Le `status` du transfert demeure la source de vérité pour l'échange lui-même.",
        "required": [
          "kind",
          "status",
          "rail",
          "attempts",
          "last_error",
          "next_attempt_at",
          "delivered_at"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "SEND",
              "ANSWER",
              "TXID",
              "CANCEL",
              "POLL"
            ],
            "description": "Ce que transporte le message. `SEND` : le premier message du transfert destiné à la contrepartie (sortant ; le réseau est choisi lors de son envoi). `ANSWER` : votre acceptation ou votre refus, dû au réseau qui en a fait la demande (entrant). `TXID` : le hash de transaction on-chain, une fois que vous avez terminé le transfert. `CANCEL` : l'annulation, une fois que vous l'avez annulé. `POLL` : une requête de statut adressée à un réseau qui en propose une, répétée toutes les 5 minutes pendant que le transfert est en attente de la contrepartie."
          },
          "status": {
            "type": "string",
            "enum": [
              "QUEUED",
              "SENDING",
              "RETRYING",
              "DELIVERED",
              "FAILED"
            ],
            "description": "`QUEUED` : en attente d'envoi. `SENDING` : une tentative est en cours. `RETRYING` : une tentative a échoué et la suivante s'exécutera à `next_attempt_at`. `DELIVERED` : l'autre partie a reçu le message. `FAILED` : l'autre partie l'a refusé, ou la dernière tentative a échoué."
          },
          "rail": {
            "type": "string",
            "enum": [
              "INTERNAL",
              "TRP",
              "GTR",
              "TRUST",
              "VERIFYVASP",
              "SYGNA",
              "EMAIL",
              ""
            ],
            "description": "Le canal qui achemine le message. Vide jusqu'à ce que Didit en ait choisi un pour un premier message."
          },
          "attempts": {
            "type": "integer",
            "minimum": 0,
            "description": "Tentatives effectuées jusqu'à présent pour ce message. Un message qui n'est pas un sondage d'état fait l'objet de 6 tentatives au maximum."
          },
          "last_error": {
            "type": "string",
            "description": "Le type d'échec rencontré lors de la dernière tentative, `\"\"` lorsqu'il n'y en a eu aucun : par exemple `email undeliverable`, `trp identity endpoint unreachable` ou `trp transfer inquiry delivery failed`. Il ne contient jamais la propre réponse de la contrepartie, qui reste sur la `timeline` du transfert.\nLorsque GTR répond par une erreur, son propre code d'état et son message sont inclus. Les corps de réponse ne sont jamais inclus.",
            "example": "email undeliverable"
          },
          "next_attempt_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où la prochaine tentative s'exécute lorsque le message est `QUEUED` ou `RETRYING`."
          },
          "delivered_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où l'autre partie a pris en charge le message."
          }
        }
      },
      "TravelRuleDiscoveryStep": {
        "type": "object",
        "description": "Une étape de la découverte de contrepartie exécutée par Didit pour un transfert sortant, dans l'ordre où elles ont été exécutées. La première étape qui désigne un VASP disposant d'une route met fin à la chaîne.",
        "properties": {
          "step": {
            "type": "string",
            "enum": [
              "internal_address_book",
              "wallet_attribution",
              "network_lookup",
              "customer_hint",
              "end_user"
            ],
            "description": "`internal_address_book` : un autre client Didit ayant prouvé le contrôle du portefeuille de destination. `wallet_attribution` : l'attribution d'analyse blockchain du portefeuille. `network_lookup` : un réseau capable d'indiquer quel VASP détient l'adresse. `customer_hint` : le nom du VASP, le LEI ou la juridiction que vous avez indiqués dans `beneficiary_data`. `end_user` : la contrepartie choisie par l'utilisateur final (ou par vous), ou la demande d'en sélectionner une."
          },
          "outcome": {
            "type": "string",
            "enum": [
              "match",
              "miss",
              "skipped"
            ],
            "description": "`match` : l'étape a identifié une contrepartie. `miss` : elle s'est exécutée et n'en a trouvé aucune. `skipped` : elle n'a pas pu s'exécuter, et `reason` en indique la raison."
          },
          "reason": {
            "type": "string",
            "description": "Raison lisible par machine, `\"\"` en cas de correspondance : `no_proven_internal_wallet`, `attribution_disabled`, `already_attributed`, `no_attributed_entity`, `directory_match_no_route`, `gtr_address_lookup_runs_on_dispatch`, `no_membership`, `network_switched_off`, `no_network_address_lookup`, `no_directory_match`, `awaiting_end_user` ou `picked_member_without_proven_wallet`."
          },
          "vasp": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Le VASP de l'annuaire désigné par l'étape, lorsqu'elle en a désigné un."
          },
          "rail": {
            "type": "string",
            "nullable": true,
            "description": "Le canal qui permet d'atteindre cette contrepartie, lorsque l'étape en a trouvé un."
          },
          "at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TravelRuleNextAction": {
        "type": "object",
        "description": "Un élément permettant de faire avancer un transfert au statut `COUNTERPARTY_VASP_NOT_FOUND` ou `COUNTERPARTY_VASP_NOT_REACHABLE`. Consultez [Pourquoi un transfert est bloqué](/fr/transaction-monitoring/travel-rule#pourquoi-un-transfert-est-bloqué).",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "select_counterparty_vasp",
              "declare_self_hosted",
              "add_vasp_hint",
              "update_compliance_email",
              "resend"
            ],
            "description": "`select_counterparty_vasp` : l'utilisateur final choisit le VASP de destination dans le widget de possession de portefeuille, ou vous effectuez un PATCH avec `action=beneficiary_vasp`. `declare_self_hosted` : l'utilisateur final déclare le portefeuille comme auto-hébergé dans le widget. `add_vasp_hint` : indiquez à Didit qui est la contrepartie, avec un nom de VASP, un LEI ou une Travel Address (par exemple une `travel_address` sur l'entrée du carnet d'adresses du portefeuille de destination), puis renvoyez. `update_compliance_email` et `resend` sont des valeurs de `action` pour `PATCH /v3/transactions/{transaction_id}/travel-rule/` : fournissez à nouveau l'e-mail de conformité de la contrepartie, et relancez le routage."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Le lien du widget de propriété du portefeuille, pour `select_counterparty_vasp` et `declare_self_hosted` tant que le transfert a une session de widget ouverte."
          }
        },
        "required": [
          "action"
        ]
      },
      "TransactionTravelRule": {
        "type": "object",
        "description": "Le transfert Travel Rule d'une transaction, tel que renvoyé par `GET /v3/transactions/{transaction_id}/`, le `201` de `POST /v3/transactions/` et chaque ligne de `GET /v3/transactions/`. `direction`, `rail`, `counterparty_vasp`, `delivery`, `discovery`, `reason` et `next_actions` ont le même format que sur `PATCH /v3/transactions/{transaction_id}/travel-rule/`, de sorte qu'une seule lecture d'une transaction indique pourquoi son transfert est bloqué et ce qui permet de le faire avancer.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "protocol": {
            "type": "string",
            "nullable": true
          },
          "required": {
            "type": "boolean"
          },
          "obligations_count": {
            "type": "integer"
          },
          "originator_data": {
            "type": "object",
            "description": "Partie du donneur d'ordre. Pour un transfert entrant, les valeurs de la contrepartie sont masquées jusqu'à ce que l'actionnariat soit confirmé."
          },
          "beneficiary_data": {
            "type": "object",
            "description": "Partie bénéficiaire. Pour un transfert entrant, les valeurs de la contrepartie sont masquées jusqu'à confirmation de la propriété."
          },
          "name_match": {
            "type": "object",
            "nullable": true,
            "description": "La comparaison de noms qui a déterminé le transfert (score et niveau d'exigence). Null tant qu'aucune comparaison n'a été exécutée. Les noms comparés sont masqués en même temps que les parties."
          },
          "data_match": {
            "$ref": "#/components/schemas/TravelRuleDataMatch"
          },
          "mismatched_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Raccourci pour `data_match.mismatched_fields`. Vide lorsque rien ne diffère."
          },
          "data_unmasked": {
            "$ref": "#/components/schemas/TravelRuleDataUnmasked"
          },
          "data_masked": {
            "type": "boolean",
            "description": "Vrai tant que les données personnelles de la contrepartie sont masquées dans cette réponse."
          },
          "metadata": {
            "type": "object"
          },
          "direction": {
            "type": "string",
            "enum": [
              "INBOUND",
              "OUTBOUND"
            ],
            "description": "De quel côté de l'échange se situe ce transfert."
          },
          "rail": {
            "type": "string",
            "nullable": true,
            "description": "Le canal par lequel le transfert est passé : `INTERNAL`, `TRP`, `GTR`, `TRUST`, `VERIFYVASP`, `SYGNA` ou `EMAIL` (`TEST_VASP` sur une application sandbox, lorsque le VASP de test Didit a répondu), ou `null` jusqu'à ce qu'un canal soit choisi."
          },
          "counterparty_vasp": {
            "type": "object",
            "nullable": true,
            "properties": {
              "name": {
                "type": "string"
              },
              "lei": {
                "type": "string"
              },
              "dd_score": {
                "type": "integer",
                "description": "Score de due diligence de 0 à 100, où une valeur plus élevée est meilleure. Même échelle que dans l'annuaire des VASP."
              },
              "dd_score_breakdown": {
                "type": "object",
                "description": "Contributions par composant au dd_score, un objet par composant comme dans le répertoire VASP (jurisdiction, verification, protocol, lei, history, essentials, responsiveness), chacun comprenant {points, max, reason, detail}. {} jusqu'à ce que la contrepartie ait été évaluée.",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "points": {
                      "type": "number",
                      "description": "Points attribués pour ce composant."
                    },
                    "max": {
                      "type": "integer",
                      "description": "Nombre maximal de points que ce composant peut attribuer."
                    },
                    "reason": {
                      "type": "string",
                      "description": "Code lisible par machine du verdict du composant."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Raison lisible par l'utilisateur pour les points attribués."
                    }
                  }
                }
              },
              "dd_assessed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure de la dernière évaluation de diligence raisonnable. Null tant que la contrepartie n'a pas été évaluée."
              }
            },
            "description": "L'entrée d'annuaire de la contrepartie, ou `null` lorsque le transfert n'en associe aucune."
          },
          "delivery": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleDelivery"
              }
            ],
            "description": "Le message le plus récent que le transfert doit à une autre partie. `null` lorsqu'aucun message n'était dû, par exemple en dessous de `threshold_amount` ou pour un portefeuille auto-hébergé déclaré."
          },
          "discovery": {
            "type": "array",
            "description": "Manière dont Didit a recherché la contrepartie, une entrée par étape exécutée. Vide lorsqu'aucune recherche n'a été effectuée, par exemple lors d'un transfert entrant.",
            "items": {
              "$ref": "#/components/schemas/TravelRuleDiscoveryStep"
            }
          },
          "reason": {
            "type": "string",
            "description": "Raison pour laquelle un transfert `COUNTERPARTY_VASP_NOT_FOUND` ou `COUNTERPARTY_VASP_NOT_REACHABLE` est bloqué ; `\"\"` pour tout autre statut. Un échec de livraison la détermine en premier, sur `COUNTERPARTY_VASP_NOT_REACHABLE` uniquement : `email_undeliverable` (le fournisseur de messagerie a refusé l'e-mail de conformité et il ne reste aucune adresse à essayer : lors de son envoi, lors d'un rappel ou sous la forme d'un rejet permanent signalé ultérieurement) ou `delivery_failed` (le canal assurant la livraison a définitivement échoué : un canal réseau a refusé le message ou a épuisé ses tentatives, un hôte d'identité `TRP` n'a pas répondu, ou l'hôte `TRP` de la contrepartie n'a pas accepté la demande). Sinon, la trace `discovery` la détermine : `awaiting_end_user` (aucune étape n'a désigné de contrepartie que Didit peut joindre), `directory_match_no_route` (une étape a désigné un VASP de l'annuaire qui ne dispose d'aucun routage), `picked_member_without_proven_wallet` (l'utilisateur final a choisi un client Didit qui n'a pas prouvé le contrôle du portefeuille) ou `no_directory_match` lorsque la trace ne donne aucune autre raison. Un nouvel envoi fait progresser le transfert, ce qui efface le motif. Voir [Pourquoi un transfert est bloqué](/fr/transaction-monitoring/travel-rule#pourquoi-un-transfert-est-bloqué)."
          },
          "next_actions": {
            "type": "array",
            "description": "Ce qui permet de faire avancer le transfert ; `[]` pour tout statut autre que `COUNTERPARTY_VASP_NOT_FOUND` ou `COUNTERPARTY_VASP_NOT_REACHABLE`. `email_undeliverable` propose `update_compliance_email`, puis `resend`. `delivery_failed` propose `resend`. Un motif lié à la découverte propose `select_counterparty_vasp`, `declare_self_hosted`, `add_vasp_hint` et `resend`.",
            "items": {
              "$ref": "#/components/schemas/TravelRuleNextAction"
            }
          },
          "chain_details": {
            "$ref": "#/components/schemas/TravelRuleChainDetails"
          }
        }
      },
      "NetworkListCounts": {
        "type": "object",
        "description": "Nombre de réseaux pour les vues de la liste et les options de filtre, chaque réseau étant compté une seule fois. Renvoyé uniquement lorsque `summary` n'est pas `false`. `scopes` compte chaque réseau visible par l'application. `views` compte les réseaux visibles au sein du `scope` sélectionné. `facets` compte les réseaux dans le `scope` sélectionné et la vue `status` (les réseaux écartés sont exclus sauf si `status` les inclut). Les autres filtres de la liste ne modifient pas ces décomptes.",
        "properties": {
          "scopes": {
            "type": "object",
            "description": "Réseaux visibles par produit.",
            "properties": {
              "all": {
                "type": "integer"
              },
              "identity": {
                "type": "integer",
                "description": "Chaque autre réseau."
              },
              "transactions": {
                "type": "integer",
                "description": "Réseaux dont les membres sont tous des parties à la transaction."
              }
            }
          },
          "views": {
            "type": "object",
            "description": "Réseaux visibles dans le `scope` sélectionné, par statut, ainsi que deux vues enregistrées.",
            "properties": {
              "all": {
                "type": "integer"
              },
              "active": {
                "type": "integer"
              },
              "in_review": {
                "type": "integer"
              },
              "resolved": {
                "type": "integer"
              },
              "dismissed": {
                "type": "integer"
              },
              "mine": {
                "type": "integer",
                "description": "Réseaux attribués au membre appelant de la console. Vaut toujours 0 pour une clé API."
              },
              "high_risk": {
                "type": "integer",
                "description": "Réseaux avec un score de risque de 80 ou plus qui ne sont pas écartés."
              }
            }
          },
          "facets": {
            "type": "object",
            "description": "Nombres d'occurrences pour chaque option de filtre, au sein du `scope` sélectionné et de la vue de statut.",
            "properties": {
              "total": {
                "type": "integer",
                "description": "Réseaux dans le `scope` sélectionné et la vue de statut."
              },
              "last_activity_days": {
                "type": "object",
                "description": "Réseaux avec une activité au cours des 7, 30 et 90 derniers jours, indexés par le nombre de jours.",
                "properties": {
                  "7": {
                    "type": "integer"
                  },
                  "30": {
                    "type": "integer"
                  },
                  "90": {
                    "type": "integer"
                  }
                }
              },
              "risk_min": {
                "type": "object",
                "description": "Réseaux avec un score de risque d'au moins 50 et d'au moins 80, indexés par seuil.",
                "properties": {
                  "50": {
                    "type": "integer"
                  },
                  "80": {
                    "type": "integer"
                  }
                }
              },
              "signal_types": {
                "type": "object",
                "description": "Réseaux avec au moins un signal de chaque type.",
                "properties": {
                  "ip_address": {
                    "type": "integer"
                  },
                  "device": {
                    "type": "integer"
                  },
                  "face": {
                    "type": "integer"
                  },
                  "document_number": {
                    "type": "integer"
                  },
                  "phone": {
                    "type": "integer"
                  },
                  "email": {
                    "type": "integer"
                  },
                  "address": {
                    "type": "integer"
                  }
                }
              },
              "priority": {
                "type": "object",
                "description": "Réseaux par priorité. `none` compte les réseaux sans priorité.",
                "properties": {
                  "low": {
                    "type": "integer"
                  },
                  "medium": {
                    "type": "integer"
                  },
                  "high": {
                    "type": "integer"
                  },
                  "none": {
                    "type": "integer"
                  }
                }
              },
              "assignee": {
                "type": "object",
                "description": "Réseaux par personne assignée.",
                "properties": {
                  "me": {
                    "type": "integer",
                    "description": "Attribué au membre de la console à l'origine de l'appel. Toujours 0 pour une clé API."
                  },
                  "unassigned": {
                    "type": "integer",
                    "description": "Attribué à personne."
                  },
                  "users": {
                    "type": "array",
                    "description": "Une entrée par personne assignée, triée par nombre décroissant de réseaux.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "full_name": {
                          "type": "string",
                          "description": "Le nom de la personne assignée, ou son e-mail lorsqu'aucun nom n'est défini."
                        },
                        "email": {
                          "type": "string"
                        },
                        "count": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              },
              "has_case": {
                "type": "integer",
                "description": "Réseaux pour lesquels cette application a ouvert un dossier."
              },
              "min_size": {
                "type": "object",
                "description": "Réseaux comptant au moins 10 membres, indexés par la taille minimale.",
                "properties": {
                  "10": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      },
      "NetworkTag": {
        "type": "object",
        "description": "L'un des tags de votre application sur le réseau.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "L'UUID de l'étiquette, la même valeur que celle transmise pour `tag_uuid`."
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "description": "Couleur hexadécimale, par exemple `#6366F1`."
          },
          "source": {
            "type": "string",
            "enum": [
              "didit",
              "custom"
            ],
            "description": "`didit` pour un tag prédéfini Didit, `custom` pour un tag créé par votre équipe."
          },
          "added_by": {
            "type": "string",
            "nullable": true,
            "description": "E-mail du membre de la console qui a ajouté le tag. Null lorsqu'une clé API l'a ajouté."
          },
          "added_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "NetworkOutcomes": {
        "type": "object",
        "description": "État des personnes et des entreprises du réseau. Chaque membre visible est comptabilisé une seule fois, selon le statut de sa vérification la plus récente ayant abouti à une décision. Les parties à la transaction ne sont pas comptabilisées.",
        "properties": {
          "approved": {
            "type": "integer",
            "description": "Membres dont la vérification décidée la plus récente a été approuvée."
          },
          "declined": {
            "type": "integer",
            "description": "Membres dont la vérification décidée la plus récente a été refusée."
          },
          "in_review": {
            "type": "integer",
            "description": "Membres dont la vérification décidée la plus récente est en cours d'examen."
          },
          "total": {
            "type": "integer",
            "description": "Membres ayant au moins une vérification, décidée ou non. Un membre dont toutes les vérifications sont indécises (non démarrée, en cours, expirée ou abandonnée) est comptabilisé ici et dans aucune autre clé."
          }
        }
      },
      "NetworkPatternScore": {
        "type": "object",
        "description": "Degré de similarité d'un type de données des membres sur l'ensemble du réseau. Un motif n'est pas un signal : aucune valeur partagée ne relie les membres.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "background"
            ],
            "description": "`background` : la similarité moyenne entre toutes les paires d'arrière-plans de selfie des membres, la personne étant masquée. Il analyse le selfie le plus récent de chaque personne, au maximum les 50 plus récents, et exclut les sessions d'assurance de l'âge. Il couvre l'ensemble du réseau, pas seulement les membres de vos applications."
          },
          "score": {
            "type": "number",
            "nullable": true,
            "minimum": 0,
            "maximum": 1,
            "description": "De 0 à 1, arrondi à 4 décimales. Null lorsque `reason` est défini."
          },
          "members": {
            "type": "integer",
            "nullable": true,
            "description": "Nombre de selfies de membres utilisés pour calculer le score. Un selfie illisible, ou montrant trop peu d'arrière-plan, n'est pas comparé. Null tant que le statut est `computing` ; 0 ou 1 avec `not_enough_selfies`."
          },
          "reason": {
            "type": "string",
            "enum": [
              "computing",
              "not_enough_selfies"
            ],
            "nullable": true,
            "description": "Raison pour laquelle il n'y a pas de score. `computing` : le score pour les membres actuels est en cours de calcul ; consultez à nouveau le réseau plus tard. `not_enough_selfies` : moins de deux membres ont un selfie utilisable. Nul lorsqu'il y a un score."
          },
          "computed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où le score a été calculé. Null pendant `computing`."
          }
        }
      },
      "NetworkDetailResponse": {
        "description": "Les détails du réseau, ainsi que le mode de partage de l'organisation, l'application ou non des signaux inter-organisations à celle-ci, les tags de votre application sur le réseau, les résultats des membres et les scores de schémas.",
        "allOf": [
          {
            "$ref": "#/components/schemas/NetworkDetail"
          },
          {
            "type": "object",
            "properties": {
              "sharing_mode": {
                "type": "string",
                "enum": [
                  "off",
                  "private",
                  "global"
                ],
                "description": "Le mode de partage inter-organisations de l'organisation. Seul `global` compare les réseaux entre organisations ; `private` et `off` les conservent dans l'historique propre à l'organisation.",
                "example": "global"
              },
              "cross_org_available": {
                "type": "boolean",
                "description": "Indique si les signaux inter-organisations s'appliquent à cette organisation. Ils nécessitent à la fois le forfait Enterprise et le mode de partage `global`.",
                "example": true
              },
              "cross_org_unavailable_reason": {
                "type": "string",
                "enum": [
                  "plan",
                  "sharing_mode"
                ],
                "nullable": true,
                "description": "Raison pour laquelle les signaux inter-organisations ne s'appliquent pas, vérifiée dans cet ordre. `plan` : le forfait de l'organisation n'inclut pas le réseau de fraude inter-organisations (le forfait Enterprise est requis), quel que soit le mode de partage. `sharing_mode` : le forfait l'inclut, mais le mode de partage est `private` ou `off`. Null lorsque `cross_org_available` est `true`.",
                "example": null
              },
              "tags": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/NetworkTag"
                },
                "description": "Les tags de votre application sur le réseau, du plus ancien au plus récent. Chaque application ne voit que ses propres tags. `fraud_tags` est distinct et inchangé : les tags que portent les membres du réseau."
              },
              "outcomes": {
                "$ref": "#/components/schemas/NetworkOutcomes"
              },
              "patterns": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/NetworkPatternScore"
                },
                "description": "Scores de motifs sur l'ensemble du réseau. Actuellement un seul élément, `background`."
              }
            }
          }
        ]
      },
      "NetworkTagRequest": {
        "type": "object",
        "required": [
          "tag_uuid"
        ],
        "properties": {
          "tag_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID de l'un des tags de votre application."
          }
        },
        "example": {
          "tag_uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
        }
      },
      "NetworkTimeline": {
        "title": "Default timeline (no contract)",
        "type": "object",
        "description": "Sans `contract` : les événements propres au réseau, du plus ancien au plus récent, non paginés.",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkTimelineEvent"
            }
          }
        }
      },
      "NetworkTimelinePage": {
        "title": "Typed timeline page (contract=2)",
        "type": "object",
        "description": "Avec `contract=2` : une page d'événements typés, les plus récents d'abord.",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkTypedTimelineEvent"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Transmettez comme `cursor` pour lire la page suivante. Null sur la dernière page."
          }
        }
      },
      "NetworkTypedTimelineEvent": {
        "type": "object",
        "description": "Un événement de chronologie typé : les quatre champs par défaut, plus son id, la date et l'heure auxquelles Didit l'a stocké, le compte membre et le dossier auxquels il appartient, ainsi que le bloc de détails correspondant à son type d'événement. Les autres blocs de détails sont null.",
        "properties": {
          "id": {
            "type": "string",
            "description": "`<source>:<uuid>`, unique au sein de la chronologie.",
            "example": "session:3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "network_detected",
              "signal_observed",
              "network_active",
              "network_in_review",
              "network_resolved",
              "network_dismissed",
              "verification_attempt",
              "transaction",
              "login",
              "rule_hit",
              "case_linked",
              "note_added"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure de l'événement."
          },
          "ingested_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles Didit l'a stocké."
          },
          "label": {
            "type": "string",
            "description": "Un court libellé en anglais, par exemple `Verification attempt 2 of 3`."
          },
          "metadata": {
            "type": "object",
            "description": "Pour les propres événements du réseau, les mêmes métadonnées que la chronologie par défaut. Vide dans le cas contraire."
          },
          "account": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineAccount"
              }
            ],
            "nullable": true,
            "description": "Le compte de membre. Null pour les événements propres au réseau, `case_linked` et `note_added`."
          },
          "source_ref": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineSourceRef"
              }
            ],
            "nullable": true,
            "description": "L'enregistrement source. Vaut null pour les événements propres au réseau et pour `note_added`."
          },
          "verification_attempt": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineAttempt"
              }
            ],
            "nullable": true,
            "description": "Défini sur les événements `verification_attempt`."
          },
          "transaction": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineTransaction"
              }
            ],
            "nullable": true,
            "description": "Défini sur les événements `transaction`."
          },
          "login": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineLogin"
              }
            ],
            "nullable": true,
            "description": "Défini sur les événements `login`."
          },
          "rule_hit": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineRuleHit"
              }
            ],
            "nullable": true,
            "description": "Défini sur les événements `rule_hit`."
          },
          "case_linked": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineCaseLinked"
              }
            ],
            "nullable": true,
            "description": "Défini sur les événements `case_linked`."
          },
          "note_added": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineNoteAdded"
              }
            ],
            "nullable": true,
            "description": "Défini sur les événements `note_added`. Jamais renvoyé à une clé API."
          }
        }
      },
      "NetworkTimelineAccount": {
        "type": "object",
        "description": "Le compte de membre auquel appartient l'événement.",
        "properties": {
          "node_id": {
            "type": "string",
            "description": "`<kind>:<uuid>`, où kind est `vendor_user`, `vendor_business` ou `transaction_party`.",
            "example": "vendor_user:3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "node_type": {
            "type": "string",
            "enum": [
              "account",
              "business_account",
              "transaction_party"
            ]
          },
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "vendor_data": {
            "type": "string",
            "nullable": true
          },
          "display_name": {
            "type": "string",
            "nullable": true
          },
          "ownership": {
            "type": "string",
            "enum": [
              "owned",
              "organization"
            ],
            "description": "`owned` lorsque l'enregistrement appartient à l'application que vous avez appelée (pour un membre de la console, à une application qui lui a été accordée). `organization` lorsqu'il appartient à une autre application de votre organisation."
          },
          "route": {
            "$ref": "#/components/schemas/NetworkTimelineRoute"
          }
        }
      },
      "NetworkTimelineSourceRef": {
        "type": "object",
        "description": "L'enregistrement à partir duquel l'événement a été lu.",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "session",
              "business_session",
              "transaction",
              "monitoring_event",
              "case"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ownership": {
            "type": "string",
            "enum": [
              "owned",
              "organization"
            ],
            "description": "`owned` lorsque l'enregistrement appartient à l'application que vous avez appelée (pour un membre de la console, à une application qui lui a été accordée). `organization` lorsqu'il appartient à une autre application de votre organisation."
          },
          "route": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineRoute"
              }
            ],
            "description": "Absent dans `monitoring_event` et `case`."
          }
        }
      },
      "NetworkTimelineRoute": {
        "type": "object",
        "description": "Informations d'ouverture de l'enregistrement : son type, son UUID et l'application à laquelle il appartient.",
        "properties": {
          "kind": {
            "type": "string",
            "description": "`user`, `business` ou `transaction_party` pour un compte ; `session`, `business_session` ou `transaction` pour un enregistrement source."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "application_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "NetworkTimelineAttempt": {
        "type": "object",
        "description": "Une session de vérification du compte.",
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "L'UUID de la session, ou l'UUID de la session d'entreprise pour une société."
          },
          "session_number": {
            "type": "integer",
            "nullable": true
          },
          "attempt": {
            "type": "integer",
            "description": "La position de cette session parmi les sessions du compte, par ordre de création."
          },
          "attempt_count": {
            "type": "integer",
            "description": "Nombre de sessions associées au compte."
          },
          "status": {
            "type": "string",
            "description": "Le statut de la session, par exemple `Approved` ou `Declined`."
          },
          "status_changed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "decline_reasons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkTimelineDeclineReason"
            },
            "description": "Pour une session refusée uniquement : ses avertissements, du plus ancien au plus récent, une seule fois par avertissement. Vide dans le cas contraire."
          }
        }
      },
      "NetworkTimelineDeclineReason": {
        "type": "object",
        "properties": {
          "risk": {
            "type": "string",
            "description": "Le code d'avertissement."
          },
          "feature": {
            "type": "string",
            "description": "La fonctionnalité qui a émis l'avertissement."
          },
          "short_description": {
            "type": "string"
          }
        }
      },
      "NetworkTimelineTransaction": {
        "type": "object",
        "description": "Une transaction à laquelle un compte membre a participé, datée par sa date de transaction.",
        "properties": {
          "transaction_id": {
            "type": "string",
            "format": "uuid"
          },
          "transaction_number": {
            "type": "integer",
            "nullable": true
          },
          "transaction_type": {
            "type": "string"
          },
          "action_type": {
            "type": "string"
          },
          "amount": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineAmount"
              }
            ],
            "nullable": true,
            "description": "Null lorsque la transaction n'a pas de montant."
          },
          "status": {
            "type": "string"
          },
          "decision_reason_code": {
            "type": "string",
            "nullable": true
          },
          "decision_reason_label": {
            "type": "string",
            "nullable": true
          },
          "party_role": {
            "type": "string",
            "description": "Le rôle du compte dans la transaction : `APPLICANT`, `REMITTER`, `BENEFICIARY` ou `COUNTERPARTY`."
          }
        }
      },
      "NetworkTimelineAmount": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "description": "Montant décimal sous forme de chaîne."
          },
          "currency": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "NetworkTimelineLogin": {
        "type": "object",
        "description": "Un événement de connexion que vous avez transmis pour une personne via l'API d'événements.",
        "properties": {
          "action": {
            "type": "string",
            "description": "`<event_category>.<action_type>` : `auth.login` ou `security.login_succeeded` pour une connexion, `auth.login_failed` ou `security.login_failed` pour un échec."
          },
          "succeeded": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "description": "Le statut de l'événement."
          },
          "ip": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineIP"
              }
            ],
            "nullable": true,
            "description": "Null lorsque l'événement n'a pas d'adresse IP."
          },
          "device": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NetworkTimelineDevice"
              }
            ],
            "nullable": true,
            "description": "Null lorsque l'événement n'a pas d'empreinte d'appareil ni de contexte."
          },
          "is_first_login": {
            "type": "boolean",
            "description": "La première connexion réussie enregistrée pour le compte."
          },
          "is_new_device": {
            "type": "boolean",
            "description": "Une connexion réussie depuis un appareil dont ne provenait aucune des connexions réussies précédentes du compte. Jamais vrai lors de la première connexion."
          }
        }
      },
      "NetworkTimelineIP": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string"
          },
          "country_code": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "connection_type": {
            "type": "string",
            "nullable": true,
            "description": "Le libellé du type de connexion pour l'adresse, sous forme de texte libre."
          },
          "is_vpn_or_tor": {
            "type": "boolean"
          },
          "is_data_center": {
            "type": "boolean"
          }
        }
      },
      "NetworkTimelineDevice": {
        "type": "object",
        "properties": {
          "fingerprint": {
            "type": "string",
            "nullable": true
          },
          "label": {
            "type": "string",
            "nullable": true,
            "description": "Un libellé d'appareil lisible construit à partir du contexte d'appareil de l'événement."
          }
        }
      },
      "NetworkTimelineRuleHit": {
        "type": "object",
        "description": "Une règle en production qui correspondait à une transaction ou à un événement d'un membre. Les correspondances en mode test ne sont pas incluses.",
        "properties": {
          "rule_id": {
            "type": "string",
            "format": "uuid"
          },
          "rule_title": {
            "type": "string"
          },
          "rule_category": {
            "type": "string"
          },
          "rule_source": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "nullable": true
          },
          "score_delta": {
            "type": "integer"
          },
          "status_target": {
            "type": "string",
            "nullable": true
          },
          "action_summary": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "NetworkTimelineCaseLinked": {
        "type": "object",
        "description": "Un dossier ouvert pour le réseau dans votre organisation. `source_ref.ownership` indique s'il appartient à l'application que vous avez appelée.",
        "properties": {
          "case_id": {
            "type": "string",
            "format": "uuid"
          },
          "case_number": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string"
          },
          "author_email": {
            "type": "string",
            "nullable": true
          },
          "author_name": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "NetworkTimelineNoteAdded": {
        "type": "object",
        "description": "Une note laissée sur le réseau. Le texte de la note n'est pas inclus.",
        "properties": {
          "note_id": {
            "type": "string",
            "format": "uuid"
          },
          "author_email": {
            "type": "string"
          }
        }
      },
      "FeatureStatusOverride": {
        "type": "object",
        "description": "Une modification manuelle (override) du statut d'une vérification (fonctionnalité) effectuée avec `PATCH /v3/session/{sessionId}/features/{nodeId}/update-status/` : ce qu'elle modifie, si elle a été appliquée ou si elle attend toujours que la personne termine le parcours, qui l'a demandée et pourquoi.",
        "required": [
          "id",
          "node_id",
          "feature_type",
          "feature_model",
          "previous_status",
          "new_status",
          "state",
          "forced",
          "reason",
          "requested_by",
          "requested_at",
          "applied_at",
          "cancelled_at",
          "cancel_reason"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de la dérogation. Transmettez-le à l'endpoint d'annulation.",
            "example": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
          },
          "node_id": {
            "type": "string",
            "description": "Le nœud de workflow spécifié dans la requête (`default` pour une étape sans nœud).",
            "example": "feature_ocr_1"
          },
          "feature_type": {
            "type": "string",
            "description": "Le `feature_type` transmis par la requête, ou une chaîne vide si aucun n'a été transmis.",
            "example": ""
          },
          "feature_model": {
            "type": "string",
            "description": "Le type de vérification qui a été remplacé, par exemple `KYC`, `Face`, `AML` ou `GeolocationCheck`.",
            "example": "KYC"
          },
          "previous_status": {
            "type": "string",
            "enum": [
              "Not Finished",
              "Approved",
              "Declined",
              "In Review",
              "Resub Requested"
            ],
            "description": "Le statut de la vérification au moment où la dérogation a été demandée.",
            "example": "In Review"
          },
          "new_status": {
            "type": "string",
            "enum": [
              "Approved",
              "Declined",
              "In Review"
            ],
            "description": "Le statut défini par la dérogation.",
            "example": "Approved"
          },
          "state": {
            "type": "string",
            "enum": [
              "applied",
              "pending_until_flow_finishes",
              "cancelled"
            ],
            "description": "`applied` : le contrôle a le nouveau statut. `pending_until_flow_finishes` : la dérogation attend et s'applique lorsque la personne termine le flux. `cancelled` : elle a attendu et ne s'est jamais appliquée (voir `cancel_reason`).",
            "example": "applied"
          },
          "forced": {
            "type": "boolean",
            "description": "`true` lorsque la dérogation s'est appliquée immédiatement alors que la personne était encore dans le flux.",
            "example": false
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "description": "Le `comment` envoyé avec la requête, ou `null`.",
            "example": "Document manually verified by compliance."
          },
          "requested_by": {
            "type": "object",
            "nullable": true,
            "description": "Qui a demandé la dérogation, ou `null` lorsque cela n'est pas connu.",
            "properties": {
              "email": {
                "type": "string",
                "format": "email",
                "nullable": true,
                "description": "E-mail de l'utilisateur de la console, ou `null` pour les clés API et le système.",
                "example": "reviewer@example.com"
              },
              "name": {
                "type": "string",
                "nullable": true,
                "description": "Nom d'affichage du demandeur, ou `null`.",
                "example": "Alex Reviewer"
              },
              "type": {
                "type": "string",
                "enum": [
                  "CONSOLE_USER",
                  "API_KEY",
                  "SYSTEM"
                ],
                "description": "Qui a effectué la requête : un utilisateur de la console, une clé API ou Didit lui-même.",
                "example": "CONSOLE_USER"
              }
            }
          },
          "requested_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où la dérogation a été demandée.",
            "example": "2026-10-13T09:15:00Z"
          },
          "applied_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles la vérification a pris le nouveau statut, ou `null` pendant qu'elle est en attente ou une fois qu'elle est annulée.",
            "example": "2026-10-13T09:15:00Z"
          },
          "cancelled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où une dérogation en attente a été annulée, ou `null`.",
            "example": null
          },
          "cancel_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "cancelled_by_reviewer",
              "replaced",
              "check_changed",
              "session_closed",
              null
            ],
            "description": "Raison pour laquelle un remplacement en attente n'a jamais été appliqué, ou `null`. `cancelled_by_reviewer` : annulé avec l'endpoint d'annulation. `replaced` : un remplacement plus récent sur la même vérification l'a remplacé. `check_changed` : la personne a refait la vérification avant de terminer le flux. `session_closed` : la session a quitté le flux avant que la personne ne le termine (abandonnée, expirée ou décidée en cours de flux).",
            "example": null
          }
        }
      },
      "SandboxSimulateRequest": {
        "type": "object",
        "description": "Forcer le statut d'une session sandbox. Chaque champ est facultatif, mais au moins l'un des champs `new_status`, `scenario` ou `risk` est requis.",
        "properties": {
          "new_status": {
            "type": "string",
            "enum": [
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned"
            ],
            "description": "Le statut à définir. Si vous ne le renseignez pas, il prend par défaut la valeur du statut par défaut du cas de risque (`risk`, ou le premier risque véhiculé par les valeurs magiques du scénario), sinon la valeur du statut par défaut du scénario.",
            "example": "Declined"
          },
          "comment": {
            "type": "string",
            "maxLength": 500,
            "description": "Note ajoutée à l'entrée d'activité enregistrée lors du changement de statut.",
            "example": "Testing the decline path"
          },
          "scenario": {
            "type": "string",
            "maxLength": 100,
            "description": "Un slug de scénario issu du catalogue (`GET /v1/sandbox/scenarios/`). Il fournit le statut par défaut et, en l'absence de `risk`, l'avertissement associé à ses valeurs magiques. Un slug inconnu renvoie `400`.",
            "example": "decline_aml_hit"
          },
          "risk": {
            "type": "string",
            "maxLength": 128,
            "description": "Un cas de risque issu du catalogue. Son avertissement est ajouté à la session, avec un type de journal qui suit `new_status`. Une valeur inconnue renvoie `400`.",
            "example": "POSSIBLE_MATCH_FOUND"
          },
          "node_id": {
            "type": "string",
            "maxLength": 128,
            "description": "Nœud de workflow auquel l'avertissement de risque est rattaché. Par défaut, le nœud actuel de la session.",
            "example": "feature_aml_1"
          },
          "send_webhooks": {
            "type": "boolean",
            "default": true,
            "description": "`true` envoie exactement les webhooks qu'un véritable changement de statut envoie aux destinations de l'application sandbox : `status.updated`, plus les événements `user.status.updated` / `user.data.updated` (ou `business.status.updated` / `business.data.updated`) provoqués par la modification, pour les destinations qui y sont abonnées. `false` modifie le statut sans consigner ni envoyer de webhook : la récupération des webhooks manqués ne renvoie jamais cette décision, la console continue de se mettre à jour en direct, et le prochain changement de statut de la session envoie des webhooks normalement.",
            "example": true
          }
        }
      },
      "SandboxSimulateResponse": {
        "type": "object",
        "required": [
          "session_id",
          "previous_status",
          "status",
          "scenario",
          "risk",
          "send_webhooks"
        ],
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "previous_status": {
            "type": "string",
            "enum": [
              "Not Started",
              "In Progress",
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned",
              "Kyc Expired",
              "Resubmitted",
              "Awaiting User"
            ],
            "description": "Le statut de la session avant la simulation.",
            "example": "In Progress"
          },
          "status": {
            "type": "string",
            "enum": [
              "Approved",
              "Declined",
              "In Review",
              "Expired",
              "Abandoned"
            ],
            "description": "Le statut défini par la simulation.",
            "example": "Declined"
          },
          "scenario": {
            "type": "string",
            "nullable": true,
            "description": "Le slug du scénario que vous avez transmis, ou `null`.",
            "example": "decline_aml_hit"
          },
          "risk": {
            "type": "string",
            "nullable": true,
            "description": "Le cas de risque appliqué (`risk`, ou celui issu du scénario), ou `null` s'il n'y en a aucun.",
            "example": "POSSIBLE_MATCH_FOUND"
          },
          "send_webhooks": {
            "type": "boolean",
            "description": "La valeur `send_webhooks` appliquée par la simulation.",
            "example": false
          }
        }
      },
      "CaseTeamSummary": {
        "type": "object",
        "nullable": true,
        "description": "L'équipe d'examen assignée au dossier, ou null si aucune équipe n'en est responsable. Le routage la définit lorsqu'une règle de routage attribue le dossier à l'une de ses équipes. Modifiez-la ou effacez-la avec `PATCH .../cases/{case_uuid}/` (`team`).",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "CaseChecker": {
        "type": "object",
        "nullable": true,
        "description": "Le membre désigné pour approuver ou rejeter la résolution en attente. Défini uniquement lorsqu'une résolution à quatre yeux attend un vérificateur désigné. Null lorsque rien n'est en attente, pendant que la résolution en attente patiente dans la file d'attente des vérificateurs, et une fois la résolution approuvée, rejetée ou renvoyée pour un nouvel examen en raison de la modification des preuves.",
        "properties": {
          "member_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "L'UUID d'utilisateur du membre : la valeur que vous transmettez comme `checker` lorsque vous résolvez le dossier."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Le nom complet du membre, ou null lorsqu'il n'est pas connu."
          },
          "email": {
            "type": "string",
            "format": "email"
          }
        }
      },
      "ServiceStatusFeed": {
        "type": "object",
        "description": "État public des services : l'état de chaque service Didit, l'état global et les incidents en cours ou résolus au cours des 7 derniers jours.",
        "required": [
          "status",
          "updated_at",
          "services",
          "incidents"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "operational",
              "degraded",
              "down"
            ],
            "description": "Le pire état parmi tous les services en ce moment, déterminé uniquement par les incidents en cours.",
            "example": "degraded"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure auxquelles Didit a généré cette réponse (ISO 8601, UTC). Les réponses sont mises en cache pendant 30 secondes, elles peuvent donc dater de 30 secondes maximum.",
            "example": "2026-10-13T09:41:07.512345Z"
          },
          "services": {
            "type": "array",
            "description": "Une entrée par service, chaque service étant toujours répertorié.",
            "items": {
              "$ref": "#/components/schemas/ServiceStatusService"
            }
          },
          "incidents": {
            "type": "array",
            "description": "Du `started_at` le plus récent au plus ancien. Tous les incidents en cours, ainsi que les incidents résolus au cours des 7 derniers jours (au maximum 50 incidents résolus). Vide si rien ne s'est produit pendant cette période.",
            "items": {
              "$ref": "#/components/schemas/ServiceStatusIncident"
            }
          }
        }
      },
      "ServiceStatusService": {
        "type": "object",
        "required": [
          "key",
          "name",
          "status"
        ],
        "properties": {
          "key": {
            "type": "string",
            "enum": [
              "service_id_verification",
              "service_liveness_face_match",
              "service_aml_screening",
              "service_kyb_registries",
              "service_database_validation",
              "service_phone_delivery",
              "service_email_delivery",
              "service_transaction_monitoring"
            ],
            "description": "Clé de service stable. Effectuez vos correspondances sur cette valeur, jamais sur le nom affiché. `service_id_verification` : Vérification d'identité, `service_liveness_face_match` : Détection du vivant et correspondance faciale, `service_aml_screening` : Filtrage AML, `service_kyb_registries` : registres KYB, `service_database_validation` : Validation en base de données, `service_phone_delivery` : Livraison de la vérification du téléphone, `service_email_delivery` : Livraison de la vérification de l'e-mail, `service_transaction_monitoring` : Surveillance des transactions.",
            "example": "service_database_validation"
          },
          "name": {
            "type": "string",
            "description": "Nom d'affichage en anglais du service.",
            "example": "Database validation"
          },
          "status": {
            "type": "string",
            "enum": [
              "operational",
              "degraded",
              "down"
            ],
            "description": "`operational` lorsqu'aucun incident n'est en cours pour le service, sinon l'état le plus critique de ses incidents en cours.",
            "example": "degraded"
          }
        }
      },
      "ServiceStatusIncident": {
        "type": "object",
        "required": [
          "id",
          "service",
          "service_name",
          "state",
          "status",
          "title",
          "body",
          "affected",
          "country_name",
          "started_at",
          "resolved_at",
          "duration_minutes"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de l'incident.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "service": {
            "type": "string",
            "enum": [
              "service_id_verification",
              "service_liveness_face_match",
              "service_aml_screening",
              "service_kyb_registries",
              "service_database_validation",
              "service_phone_delivery",
              "service_email_delivery",
              "service_transaction_monitoring"
            ],
            "description": "Clé du service concerné (voir `services[].key`).",
            "example": "service_database_validation"
          },
          "service_name": {
            "type": "string",
            "description": "Nom d'affichage en anglais du service concerné.",
            "example": "Database validation"
          },
          "state": {
            "type": "string",
            "enum": [
              "degraded",
              "down"
            ],
            "description": "Comment le service est affecté. Un incident résolu conserve le dernier état qu'il avait.",
            "example": "degraded"
          },
          "status": {
            "type": "string",
            "enum": [
              "ongoing",
              "resolved"
            ],
            "description": "`ongoing` jusqu'à ce que le service soit rétabli, puis `resolved`.",
            "example": "ongoing"
          },
          "title": {
            "type": "string",
            "description": "Titre en anglais. Pour le traduire, construisez votre propre texte à partir de `service`, `state` et `country_name`.",
            "example": "Database validation is degraded in Brazil."
          },
          "body": {
            "type": "string",
            "description": "Ligne de détail en anglais : depuis quand les vérifications peuvent être lentes ou échouer, ou quand le service s'est rétabli.",
            "example": "Checks against Brazil (CPF) may be slow or fail since 08:55 UTC."
          },
          "affected": {
            "type": "string",
            "description": "Pays ou registres concernés, par exemple `Brazil (CPF)`. Vide lorsque l'incident n'est pas lié à un pays ou à un registre.",
            "example": "Brazil (CPF)"
          },
          "country_name": {
            "type": "string",
            "description": "Pays concerné, en anglais. Vide lorsque l'incident n'est pas lié à un pays.",
            "example": "Brazil"
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "description": "Moment où l'incident a commencé (ISO 8601, UTC).",
            "example": "2026-10-13T08:55:00Z"
          },
          "resolved_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Moment où le service s'est rétabli (ISO 8601, UTC). `null` tant que l'incident est en cours."
          },
          "duration_minutes": {
            "type": "integer",
            "nullable": true,
            "description": "Minutes entières écoulées entre `started_at` et `resolved_at`. `null` tant que l'incident est en cours."
          }
        }
      },
      "TravelRuleJoinInvitation": {
        "type": "object",
        "description": "Ce que la page de participation affiche avant toute saisie.",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "L'adresse à laquelle l'invitation a été envoyée."
          },
          "vasp_name": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "description": "Origine de l'invitation, par exemple `pickup`."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "prefill": {
            "type": "object",
            "properties": {
              "vasp_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true
              },
              "legal_name": {
                "type": "string"
              },
              "lei": {
                "type": "string"
              },
              "jurisdiction": {
                "type": "string"
              },
              "domains": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "TravelRuleJoinRegisterRequest": {
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254,
            "description": "Doit être l'adresse à laquelle l'invitation a été envoyée."
          },
          "password": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128
          }
        }
      },
      "TravelRuleJoinVerifyRequest": {
        "type": "object",
        "required": [
          "email",
          "code"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "code": {
            "type": "string",
            "minLength": 6,
            "maxLength": 6,
            "description": "Le code à 6 caractères envoyé par e-mail après l'inscription."
          }
        }
      },
      "TravelRuleJoinCredentials": {
        "type": "object",
        "description": "La nouvelle organisation gratuite et les identifiants avec lesquels son application appelle l'API.",
        "properties": {
          "organization": {
            "type": "object",
            "properties": {
              "uuid": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "application": {
            "type": "object",
            "properties": {
              "uuid": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "client_id": {
            "type": "string"
          },
          "api_key": {
            "type": "string",
            "description": "Envoyez dans l'en-tête `x-api-key` sur les endpoints de l'espace de travail."
          }
        }
      },
      "TravelRuleWorkspaceClaimRequest": {
        "type": "object",
        "required": [
          "vasp_id"
        ],
        "properties": {
          "vasp_id": {
            "type": "string",
            "format": "uuid",
            "description": "L'entrée de l'annuaire correspondant à cet espace de travail. Récupérez les identifiants depuis `GET /v3/travel-rule/vasps/`."
          }
        }
      },
      "TravelRuleWorkspaceDomainConfirmRequest": {
        "type": "object",
        "required": [
          "code"
        ],
        "properties": {
          "code": {
            "type": "string",
            "minLength": 6,
            "maxLength": 6
          }
        }
      },
      "TravelRuleWorkspaceBillingRequest": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "default": true,
            "description": "Seul `true` est accepté : la facturation sortante ne peut pas être désactivée via l'API."
          }
        }
      },
      "TravelRuleWorkspaceDomainCodeResponse": {
        "type": "object",
        "properties": {
          "domain": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "unverified",
              "code_sent",
              "verified"
            ]
          },
          "txt": {
            "$ref": "#/components/schemas/TravelRuleWorkspaceTxtRecord"
          }
        }
      },
      "TravelRuleWorkspaceTxtRecord": {
        "type": "object",
        "description": "L'enregistrement TXT à publier pour la preuve DNS. Vide jusqu'à ce qu'une preuve soit lancée.",
        "properties": {
          "host": {
            "type": "string",
            "example": "didit-tr-verify.example.com"
          },
          "value": {
            "type": "string"
          }
        }
      },
      "TravelRuleWorkspace": {
        "type": "object",
        "description": "L'espace de travail Travel Rule gratuit d'une application ayant rejoint l'offre gratuite.",
        "properties": {
          "joined_free": {
            "type": "boolean"
          },
          "work_email": {
            "type": "string",
            "format": "email"
          },
          "joined_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "claim": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "unclaimed",
                  "pending_review",
                  "claimed",
                  "rejected"
                ]
              },
              "proved_by_domain": {
                "type": "boolean"
              },
              "claimed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "reviewed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "review_note": {
                "type": "string"
              },
              "vasp_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true
              },
              "vasp_name": {
                "type": "string"
              }
            }
          },
          "prefill": {
            "type": "object",
            "description": "Valeurs du profil issues de l'entrée de l'annuaire : `vasp_id`, `legal_name`, `lei`, `jurisdiction`, `compliance_email`, `domains`. Rien n'est écrit tant que la revendication n'est pas effectuée."
          },
          "domain": {
            "type": "object",
            "properties": {
              "domain": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "unverified",
                  "code_sent",
                  "verified"
                ]
              },
              "verified_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "txt": {
                "$ref": "#/components/schemas/TravelRuleWorkspaceTxtRecord"
              }
            }
          },
          "billing_enabled": {
            "type": "boolean",
            "description": "La réception des données Travel Rule est gratuite. L'envoi n'est facturé qu'après l'activation de la facturation."
          },
          "billing_enabled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "didit_network": {
            "type": "object",
            "description": "Indique si le réseau Didit répertorie ce VASP et, si ce n'est pas le cas, chaque condition qui lui manque encore."
          },
          "settings": {
            "$ref": "#/components/schemas/TravelRuleSettingsDetail"
          }
        }
      },
      "InvestigatorDecision": {
        "type": "object",
        "description": "Manière dont l'élément a quitté la file d'attente de l'Investigator. `decided_by`, `original_outcome` et `overrides` sont renvoyés par les endpoints d'acceptation et de dérogation ainsi que par le rapport ; le bloc `investigator` d'une décision de session contient les autres champs.",
        "properties": {
          "outcome": {
            "type": "string",
            "enum": [
              "accepted",
              "edited",
              "overridden",
              "decided_elsewhere",
              "automated"
            ],
            "description": "`accepted` ou `edited` a suivi la recommandation (`edited` avec un descriptif réécrit), `overridden` a appliqué une autre action, `decided_elsewhere` est une décision prise en dehors de l'Investigator alors que le rapport était ouvert, `automated` est une décision que l'Investigator a prise de lui-même."
          },
          "action": {
            "type": "string",
            "enum": [
              "approve",
              "decline",
              "escalate",
              "request"
            ]
          },
          "actor_email": {
            "type": "string",
            "nullable": true
          },
          "actor_name": {
            "type": "string",
            "nullable": true
          },
          "override_category": {
            "type": "string",
            "enum": [
              "missing_context",
              "needs_information",
              "policy_differs",
              "evidence_misread",
              "other",
              ""
            ],
            "nullable": true
          },
          "override_reason": {
            "type": "string",
            "nullable": true
          },
          "final_status": {
            "type": "string",
            "description": "Le statut de l'élément après la décision."
          },
          "agreed": {
            "type": "boolean",
            "description": "Indique si la décision correspond à la recommandation.",
            "nullable": true
          },
          "decided_at": {
            "type": "string",
            "format": "date-time"
          },
          "billed": {
            "type": "boolean",
            "description": "L'examen a été facturé."
          },
          "decided_by": {
            "type": "string",
            "enum": [
              "investigator",
              "member"
            ]
          },
          "original_outcome": {
            "type": "object",
            "description": "La décision que l'Investigator a prise de lui-même, inchangée malgré les remplacements ultérieurs. Null pour une décision prise par l'équipe.",
            "properties": {
              "action": {
                "type": "string"
              },
              "final_status": {
                "type": "string"
              },
              "decided_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "nullable": true
          },
          "overrides": {
            "type": "array",
            "description": "Chaque dérogation à une décision que l'Investigator a prise de lui-même, de la plus ancienne à la plus récente.",
            "items": {
              "type": "object",
              "properties": {
                "action": {
                  "type": "string"
                },
                "actor_email": {
                  "type": "string",
                  "nullable": true
                },
                "actor_name": {
                  "type": "string",
                  "nullable": true
                },
                "override_category": {
                  "type": "string"
                },
                "override_reason": {
                  "type": "string"
                },
                "previous_status": {
                  "type": "string"
                },
                "final_status": {
                  "type": "string"
                },
                "agreed": {
                  "type": "boolean",
                  "nullable": true
                },
                "overridden_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "InvestigatorBlock": {
        "type": "object",
        "nullable": true,
        "description": "Le dernier examen Investigator de l'élément, ou null s'il n'en a jamais eu. Porté par la décision de session V3 et de session d'entreprise (et donc par les webhooks `status.updated`).",
        "properties": {
          "run_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "completed",
              "failed"
            ]
          },
          "stage": {
            "type": "string",
            "enum": [
              "shadow",
              "live"
            ]
          },
          "queue": {
            "type": "string",
            "enum": [
              "kyc",
              "kyb",
              "aml",
              "transactions",
              "cases"
            ]
          },
          "is_open": {
            "type": "boolean"
          },
          "recommendation": {
            "type": "string",
            "enum": [
              "approve",
              "decline",
              "escalate",
              "request"
            ],
            "nullable": true
          },
          "recommendation_detail": {
            "type": "string",
            "nullable": true
          },
          "confidence": {
            "type": "string",
            "enum": [
              "high",
              "moderate",
              "low"
            ],
            "nullable": true
          },
          "summary": {
            "type": "string",
            "nullable": true
          },
          "ready_to_accept": {
            "type": "boolean"
          },
          "prepared_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "automated": {
            "type": "boolean",
            "description": "L'Investigator a pris la décision seul, même si la décision a été modifiée par la suite."
          },
          "decided_by": {
            "type": "string",
            "enum": [
              "investigator",
              "member"
            ],
            "nullable": true
          },
          "decision": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/InvestigatorDecision"
              }
            ],
            "type": "object"
          }
        }
      },
      "InvestigatorQueueRow": {
        "type": "object",
        "properties": {
          "run_id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "session",
              "business_session",
              "transaction",
              "case"
            ]
          },
          "queue": {
            "type": "string",
            "enum": [
              "kyc",
              "kyb",
              "aml",
              "transactions",
              "cases"
            ]
          },
          "stage": {
            "type": "string",
            "enum": [
              "shadow",
              "live"
            ]
          },
          "subject": {
            "type": "object",
            "description": "L'élément en cours d'examen : `id`, `number`, `status`, `name` et, selon le type, `country`, `workflow`, `vendor_data`, `txn_id`, `amount`, `currency`, `direction`, `title` ou `priority`.",
            "additionalProperties": true
          },
          "recommendation": {
            "type": "string",
            "enum": [
              "approve",
              "decline",
              "escalate",
              "request"
            ]
          },
          "recommendation_detail": {
            "type": "string"
          },
          "confidence": {
            "type": "string",
            "enum": [
              "high",
              "moderate",
              "low"
            ]
          },
          "summary": {
            "type": "string"
          },
          "sources_count": {
            "type": "integer"
          },
          "ready_to_accept": {
            "type": "boolean"
          },
          "guardrails": {
            "description": "Les garde-fous verrouillés qui s'appliquent à cet élément, le cas échéant."
          },
          "waiting_since": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "due_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "prepared_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "InvestigatorRunDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InvestigatorQueueRow"
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "type": "string"
              },
              "is_open": {
                "type": "boolean"
              },
              "lookups": {
                "type": "integer",
                "description": "Nombre de sections et d'enregistrements liés lus."
              },
              "duration_ms": {
                "type": "integer",
                "nullable": true
              },
              "agent_version": {
                "type": "string"
              },
              "prepared_before_opened": {
                "type": "boolean",
                "nullable": true
              },
              "report": {
                "type": "object",
                "additionalProperties": true,
                "description": "Le rapport : raisonnement, éléments de preuve avec leur verdict (`ok`, `risk`, `look`, `explained`, `context`) et sources citées, verdicts des correspondances de filtrage (`same`, `not_same`, `unclear`) et prochaines étapes suggérées."
              },
              "trail": {
                "description": "Ce que j'ai vérifié : la vue d'ensemble, les sections et les enregistrements lus, dans l'ordre."
              },
              "decision": {
                "nullable": true,
                "allOf": [
                  {
                    "$ref": "#/components/schemas/InvestigatorDecision"
                  }
                ],
                "type": "object"
              },
              "autonomy": {
                "type": "object",
                "additionalProperties": true,
                "description": "Traitement autonome appliqué au rapport (`result`, `reason`, `tier`, `policy_version`, `rule`, `agreement`, `decisions`, `threshold`, `at`). Null lorsque la file d'attente n'est pas automatisée.",
                "nullable": true
              }
            }
          }
        ]
      },
      "InvestigatorAcceptRequest": {
        "type": "object",
        "properties": {
          "narrative": {
            "type": "string",
            "maxLength": 4000,
            "description": "Un narratif réécrit. En envoyer un enregistre la décision comme modifiée et acceptée."
          },
          "send_email": {
            "type": "boolean",
            "default": false,
            "description": "Informer la personne de la décision par e-mail."
          },
          "email_address": {
            "type": "string",
            "format": "email",
            "description": "Requis lorsque `send_email` est true."
          },
          "email_language": {
            "type": "string",
            "default": "en",
            "maxLength": 16
          }
        }
      },
      "InvestigatorOverrideRequest": {
        "type": "object",
        "required": [
          "action",
          "category",
          "reason"
        ],
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "approve",
              "decline",
              "escalate",
              "request"
            ]
          },
          "category": {
            "type": "string",
            "enum": [
              "missing_context",
              "needs_information",
              "policy_differs",
              "evidence_misread",
              "other"
            ]
          },
          "reason": {
            "type": "string",
            "minLength": 10,
            "maxLength": 500
          },
          "send_email": {
            "type": "boolean",
            "default": false,
            "description": "Informer la personne de la décision par e-mail."
          },
          "email_address": {
            "type": "string",
            "format": "email",
            "description": "Requis lorsque `send_email` est true."
          },
          "email_language": {
            "type": "string",
            "default": "en",
            "maxLength": 16
          }
        }
      },
      "InvestigatorBatchAcceptRequest": {
        "type": "object",
        "required": [
          "run_ids"
        ],
        "properties": {
          "run_ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "InvestigatorBatchAcceptResponse": {
        "type": "object",
        "properties": {
          "accepted": {
            "type": "integer"
          },
          "skipped": {
            "type": "integer"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "run_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "result": {
                  "type": "string",
                  "enum": [
                    "accepted",
                    "skipped"
                  ]
                },
                "reason": {
                  "type": "string",
                  "enum": [
                    "not_found",
                    "forbidden",
                    "already_decided",
                    "not_ready",
                    "guardrail",
                    "invalid"
                  ]
                },
                "detail": {},
                "action": {
                  "type": "string"
                },
                "final_status": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "InvestigatorSettings": {
        "type": "object",
        "properties": {
          "stage": {
            "type": "string",
            "enum": [
              "none",
              "shadow",
              "live"
            ]
          },
          "stage_changed_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "nullable": true
          },
          "stage_changed_by": {
            "type": "string",
            "readOnly": true
          },
          "monthly_spend_limit": {
            "type": "string",
            "format": "decimal",
            "description": "Plafond mensuel dans votre devise de facturation, de 0.01 à 1,000,000. Null le désactive.",
            "nullable": true
          },
          "spend_limit": {
            "type": "object",
            "readOnly": true,
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "limit": {
                "type": "string",
                "format": "decimal",
                "nullable": true
              },
              "spent": {
                "type": "string",
                "format": "decimal"
              },
              "reviews": {
                "type": "integer"
              },
              "reserved": {
                "type": "string",
                "format": "decimal",
                "description": "Le prix de chaque rapport en production ouvert, retenu car son acceptation déclenche sa facturation."
              },
              "currency": {
                "type": "string"
              },
              "paused": {
                "type": "boolean",
                "description": "À la limite : aucun nouvel examen ne démarre."
              }
            }
          }
        }
      },
      "TravelRuleUtxoEntry": {
        "type": "object",
        "description": "Une entrée ou une sortie d'une transaction UTXO, telle qu'enregistrée par la blockchain.",
        "required": [
          "address"
        ],
        "properties": {
          "address": {
            "type": "string",
            "maxLength": 128
          },
          "amount": {
            "type": "string",
            "nullable": true,
            "description": "Chaîne décimale dans l'unité propre à la crypto-monnaie (BTC, et non en satoshis). Facultatif.",
            "example": "0.0125"
          },
          "txid": {
            "type": "string",
            "maxLength": 128,
            "description": "Facultatif. La transaction dépensée par une entrée."
          },
          "vout": {
            "type": "integer",
            "nullable": true,
            "minimum": 0,
            "description": "Facultatif. L'index de sortie dépensé par une entrée."
          }
        }
      },
      "TravelRuleUtxo": {
        "type": "object",
        "description": "Les entrées et sorties d'un transfert UTXO (BTC, LTC, BCH, DOGE). Uniquement accepté sur ces blockchains : sur toute autre blockchain, cela génère un `400`. À partir de celles-ci, Didit déduit le portefeuille du donneur d'ordre (celui déclaré, sinon l'adresse d'entrée ayant le plus contribué) et la sortie du bénéficiaire (celle déclarée, sinon la seule sortie qui ne rembourse pas une adresse d'entrée en tant que monnaie rendue, sinon la sortie réglant le montant du transfert). Le résultat figure sur le `chain_details` du transfert.",
        "required": [
          "outputs"
        ],
        "properties": {
          "inputs": {
            "type": "array",
            "maxItems": 1000,
            "items": {
              "$ref": "#/components/schemas/TravelRuleUtxoEntry"
            },
            "description": "Facultatif. Sans entrées, aucun donneur d'ordre n'est déduit et aucune sortie de change n'est reconnue."
          },
          "outputs": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "items": {
              "$ref": "#/components/schemas/TravelRuleUtxoEntry"
            }
          }
        }
      },
      "TravelRuleChainSide": {
        "type": "object",
        "description": "Le portefeuille de l'une des parties, tel que Didit l'a résolu à partir des données de la blockchain.",
        "properties": {
          "address": {
            "type": "string",
            "description": "Le portefeuille. Sur un réseau à mémo, l'adresse classique (une X-address XRP est divisée en son adresse classique et son tag) ; sur Lightning, l'identifiant du nœud du bénéficiaire ou la Lightning Address."
          },
          "memo": {
            "type": "string",
            "description": "Le tag de destination ou mémo faisant partie du portefeuille ; `\"\"` en l'absence de mémo."
          },
          "source": {
            "type": "string",
            "enum": [
              "declared",
              "x_address",
              "largest_input",
              "only_non_change_output",
              "amount_match",
              "invoice_payee",
              "updated"
            ],
            "description": "Origine du portefeuille : `declared` (votre requête), `x_address` (dérivée d'une adresse X XRP), `largest_input` (l'adresse d'entrée UTXO ayant le plus contribué), `only_non_change_output` (la seule sortie UTXO qui n'est pas de la monnaie rendue), `amount_match` (l'unique sortie UTXO payant le montant du transfert), `invoice_payee` (le bénéficiaire désigné par une demande de paiement Lightning), `updated` (défini ultérieurement avec `action: update_originator_wallet`)."
          }
        }
      },
      "TravelRuleChainDetails": {
        "type": "object",
        "description": "Manière dont la blockchain du transfert nomme ses deux portefeuilles, lorsque plus d'une adresse en paie une autre. Vide (`{}`) pour un transfert sur une blockchain basée sur des comptes (EVM, Solana, Tron), où les deux adresses sont les portefeuilles. La correspondance, le routage et le carnet d'adresses lisent d'abord les portefeuilles ici.",
        "properties": {
          "chain": {
            "type": "string",
            "description": "Blockchain canonique, par ex. `BTC`, `XRP`, ou `LIGHTNING` pour un transfert Lightning."
          },
          "shape": {
            "type": "string",
            "enum": [
              "utxo",
              "memo",
              "lightning"
            ]
          },
          "originator": {
            "$ref": "#/components/schemas/TravelRuleChainSide"
          },
          "beneficiary": {
            "$ref": "#/components/schemas/TravelRuleChainSide"
          },
          "utxo": {
            "type": "object",
            "description": "Sur un transfert UTXO : les entrées et sorties telles qu'enregistrées (montants sous forme de chaînes décimales) et la manière dont Didit a interprété chaque sortie.",
            "properties": {
              "inputs": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TravelRuleUtxoEntry"
                }
              },
              "outputs": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TravelRuleUtxoEntry"
                }
              },
              "change_output_indexes": {
                "type": "array",
                "items": {
                  "type": "integer"
                },
                "description": "Sorties qui remboursent une adresse d'entrée."
              },
              "beneficiary_output_index": {
                "type": "integer",
                "nullable": true,
                "description": "La sortie qui paie le bénéficiaire ; null lorsqu'aucune n'a pu être distinguée."
              }
            }
          },
          "lightning": {
            "type": "object",
            "description": "Sur un transfert Lightning : ce qu'indique la demande de paiement. Toujours `kind` (`bolt11`, `bolt12_offer`, `bolt12_invoice`, `bolt12_invoice_request`, `lnurl`, `lightning_address`, `node_id` ou `unknown`) ; une facture BOLT11 ajoute `network`, `payee_node_id`, `payment_hash`, `amount_msat`, `created_at` et `expires_at` ; une chaîne BOLT12 ajoute `blinded_paths` et `payee_node_id` ; un LNURL ou une adresse Lightning ajoute son `domain`. Rien n'est résolu sur le réseau : la requête est uniquement décodée.",
            "additionalProperties": true
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "declared_originator_not_an_input",
                "declared_beneficiary_not_an_output",
                "beneficiary_output_ambiguous",
                "beneficiary_output_amount_differs"
              ]
            },
            "description": "Incohérences UTXO nécessitant une vérification : le donneur d'ordre déclaré n'est pas une entrée, le bénéficiaire déclaré n'est pas une sortie, aucune sortie de bénéficiaire unique n'a pu être distinguée, ou la sortie du bénéficiaire paie un montant différent de celui indiqué par la transaction."
          },
          "not_applicable_reason": {
            "type": "string",
            "enum": [
              "LIGHTNING_NO_PAYEE_IDENTIFIER",
              "LIGHTNING_BOLT12_BLINDED_PAYEE",
              "LIGHTNING_LNURL_NAMES_NO_PAYEE"
            ],
            "description": "Sur un transfert Lightning sortant dont la demande de paiement ne mentionne aucun bénéficiaire : pourquoi le transfert est `NOT_APPLICABLE`. `LIGHTNING_NO_PAYEE_IDENTIFIER` (la demande ne mentionne aucun nœud bénéficiaire ou n'a pas pu être décodée), `LIGHTNING_BOLT12_BLINDED_PAYEE` (l'offre dissimule son bénéficiaire derrière des chemins aveugles), `LIGHTNING_LNURL_NAMES_NO_PAYEE` (un LNURL désigne un service, pas un bénéficiaire). Le même code ouvre la dernière entrée de la `timeline` du transfert."
          }
        }
      },
      "WalletAddressImportRow": {
        "type": "object",
        "description": "Un portefeuille à importer : par son `address`, son `address_hash`, ou les deux. Les variantes en camelCase de ces champs sont également acceptées, tout comme `walletAddress`, `walletAddressHash`, `destinationTag` et `externalUserId`.",
        "properties": {
          "address": {
            "type": "string",
            "maxLength": 128,
            "description": "L'adresse du portefeuille. Alias : `walletAddress`."
          },
          "address_hash": {
            "type": "string",
            "description": "SHA-256 de l'adresse en minuscules, sous forme de 64 caractères hexadécimaux ou 44 caractères base64. Envoyez-le seul pour enregistrer un portefeuille sans divulguer son adresse ; envoyé avec `address`, il doit s'agir du hachage de cette adresse. Alias : `walletAddressHash`."
          },
          "chain": {
            "type": "string",
            "maxLength": 32
          },
          "memo": {
            "type": "string",
            "maxLength": 256,
            "description": "Le tag de destination ou mémo. XRP : un tag de destination, un nombre entier de 0 à 4294967295 (un nombre JSON est accepté). XLM : un mémo texte jusqu'à 28 octets, un identifiant 64 bits ou un hachage de 32 octets en hexadécimal. EOS : jusqu'à 256 octets. ATOM : jusqu'à 256 caractères. HBAR : jusqu'à 100 octets. Les portefeuilles Bitcoin, EVM, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin et Lightning n'acceptent aucun mémo : en fournir un renvoie une erreur `400`."
          },
          "holder_name": {
            "type": "string",
            "maxLength": 255
          },
          "holder_vendor_data": {
            "type": "string",
            "maxLength": 255,
            "description": "Votre identifiant interne pour le titulaire. Alias : `externalUserId`."
          },
          "entity_type": {
            "type": "string",
            "enum": [
              "individual",
              "company"
            ],
            "default": "individual"
          },
          "label": {
            "type": "string",
            "maxLength": 255
          },
          "owner_type": {
            "type": "string",
            "enum": [
              "customer",
              "internal",
              "vasp"
            ],
            "default": "customer"
          },
          "travel_address": {
            "type": "string",
            "maxLength": 512
          },
          "self_declared": {
            "type": "boolean",
            "default": false,
            "description": "Créer l'entrée déjà vérifiée via une autodéclaration, lorsque vos paramètres l'autorisent."
          }
        }
      },
      "WalletAddressImportReport": {
        "type": "object",
        "description": "Ce qui est arrivé à chaque ligne d'une importation, dans l'ordre d'envoi.",
        "properties": {
          "total": {
            "type": "integer"
          },
          "created": {
            "type": "integer"
          },
          "existing": {
            "type": "integer"
          },
          "duplicate": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "row": {
                  "type": "integer",
                  "description": "Le numéro de la ligne, à partir de 1."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "created",
                    "existing",
                    "duplicate",
                    "failed"
                  ],
                  "description": "`created` : ajouté au carnet. `existing` : le portefeuille est déjà dans le carnet et n'a pas été modifié. `duplicate` : répète une ligne antérieure de cet import. `failed` : voir `errors`."
                },
                "entry_id": {
                  "type": "string",
                  "format": "uuid",
                  "nullable": true,
                  "description": "L'entrée du carnet d'adresses créée ou trouvée par la ligne."
                },
                "errors": {
                  "type": "object",
                  "description": "Erreurs de champ d'une ligne `failed` ; vide dans le cas contraire."
                },
                "duplicate_of_row": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Sur une ligne `duplicate`, la ligne qu'elle répète."
                }
              }
            }
          }
        }
      },
      "TravelRuleCounterpartyContact": {
        "type": "object",
        "description": "Une adresse de conformité vers laquelle le canal EMAIL écrit pour une entrée de l'annuaire.",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "counterparty": {
            "type": "string",
            "format": "uuid",
            "description": "Le champ `id` de l'entrée de l'annuaire, tel qu'affiché par GET /v3/travel-rule/vasps/."
          },
          "counterparty_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string",
            "description": "Libellé optionnel, par exemple le nom de l'équipe."
          },
          "source": {
            "type": "string",
            "enum": [
              "staff",
              "application",
              "learned"
            ],
            "description": "staff : sélectionné par Didit. learned : une adresse sur l'un des domaines propres du VASP ayant répondu à une requête via son lien de réponse. application : ajouté par votre application."
          },
          "scope": {
            "type": "string",
            "enum": [
              "platform",
              "application"
            ],
            "description": "platform : sélectionné par Didit ou déduit d'une réponse vérifiée, utilisé pour chaque client de Didit, en lecture seule pour vous. application : privé pour votre application."
          },
          "created_by": {
            "type": "string",
            "description": "Vide pour les contacts de la plateforme et pour les contacts ajoutés par une clé API."
          },
          "verified_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles cette adresse a répondu pour la dernière fois à une requête via son lien de réponse."
          },
          "is_invalid": {
            "type": "boolean",
            "description": "true une fois que l'adresse a fait l'objet d'un rebond ou d'une réclamation ; le canal EMAIL l'ignore."
          },
          "invalid_reason": {
            "type": "string",
            "enum": [
              "",
              "hard_bounce",
              "soft_bounce",
              "spam_complaint",
              "suppressed"
            ]
          },
          "invalid_detail": {
            "type": "string",
            "description": "Le motif du serveur de messagerie de réception, lorsqu'il en a fourni un."
          },
          "invalid_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TravelRuleCounterpartyContactCreate": {
        "type": "object",
        "required": [
          "counterparty",
          "email"
        ],
        "properties": {
          "counterparty": {
            "type": "string",
            "format": "uuid",
            "description": "L'`id` de l'entrée de l'annuaire."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "name": {
            "type": "string",
            "description": "Libellé optionnel.",
            "maxLength": 255
          }
        }
      },
      "TravelRuleNameMatch": {
        "type": "object",
        "nullable": true,
        "description": "La comparaison de noms qui a déterminé le transfert, ou null tant qu'aucune n'a été exécutée. Lorsque les parties sont masquées, ainsi que sur la copie de l'autre client d'un échange INTERNAL, `transfer_name`, `compared_name`, `matched_names` et `mismatched_names` sont masqués. `score` et `matched` peuvent différer : `matched` suit le niveau d'exigence, `score` correspond à la similarité entre les deux noms complets.",
        "properties": {
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Similarité des deux noms complets, de 0 à 100. 0 si l'un des deux noms est vide."
          },
          "matched": {
            "type": "boolean",
            "description": "Indique si les noms satisfont à `strictness`. L'issue du transfert dépend de `data_match`, qui compare chaque champ ; un transfert peut donc être COUNTERPARTY_MISMATCHED_DATA alors que cette valeur est vraie."
          },
          "method": {
            "type": "string",
            "enum": [
              "none",
              "exact_token",
              "token_subset",
              "token_containment",
              "sequence_ratio"
            ],
            "description": "Manière dont `matched` a été déterminé : none (`NONE`), exact_token (`STRICT`), token_subset (`DEFAULT`), token_containment (`CONTAINS`) ou sequence_ratio (`FUZZY`)."
          },
          "strictness": {
            "type": "string",
            "enum": [
              "NONE",
              "STRICT",
              "CONTAINS",
              "DEFAULT",
              "FUZZY"
            ]
          },
          "compared_with": {
            "type": "string",
            "enum": [
              "wallet_holder",
              "counterparty_vasp"
            ],
            "description": "wallet_holder : le titulaire enregistré pour le portefeuille. counterparty_vasp : le nom fourni par la contrepartie sur la page de réponse par e-mail, ou la réponse du VASP de test Didit dans le sandbox."
          },
          "transfer_name": {
            "type": "string",
            "description": "Le nom figurant sur le transfert."
          },
          "compared_name": {
            "type": "string",
            "description": "Le nom avec lequel il a été comparé."
          },
          "matched_names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Mots de `transfer_name` trouvés dans `compared_name`."
          },
          "mismatched_names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Mots de `transfer_name` absents de `compared_name`, puis mots de `compared_name` absents de `transfer_name`."
          }
        }
      },
      "TravelRuleTransferRow": {
        "type": "object",
        "description": "Un transfert Travel Rule tel que la liste des transferts l'affiche : noms des VASP, portefeuilles et mémos uniquement, jamais les données personnelles du donneur d'ordre ou du bénéficiaire.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "L'identifiant du transfert."
          },
          "transaction_id": {
            "type": "string",
            "format": "uuid",
            "description": "La transaction Didit à laquelle appartient le transfert."
          },
          "txn_id": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre identifiant pour la transaction. Les transferts que Didit enregistre pour vous, comme un transfert entrant Didit Test VASP, en portent un généré automatiquement."
          },
          "txn_date": {
            "type": "string",
            "format": "date-time"
          },
          "kind": {
            "type": "string",
            "enum": [
              "withdrawal",
              "deposit",
              "message"
            ],
            "description": "withdrawal : sortant. message : un transfert entrant qu'un canal a créé à partir du message d'une contrepartie (une demande TRP, la partie entrante INTERNAL, ou un message GTR, VerifyVASP ou Sygna Bridge). deposit : tout autre transfert entrant."
          },
          "direction": {
            "type": "string",
            "enum": [
              "INBOUND",
              "OUTBOUND"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "AWAITING_COUNTERPARTY",
              "ON_HOLD",
              "COMPLETED",
              "FINISHED",
              "CANCELLED",
              "EXPIRED",
              "COUNTERPARTY_MISMATCHED_DATA",
              "COUNTERPARTY_VASP_NOT_FOUND",
              "COUNTERPARTY_VASP_NOT_REACHABLE",
              "UNCONFIRMED_OWNERSHIP",
              "COUNTERPARTY_VASP_GENERAL_DECLINE",
              "NOT_ENOUGH_COUNTERPARTY_DATA",
              "NOT_APPLICABLE"
            ]
          },
          "reason": {
            "type": "string",
            "description": "Raison pour laquelle un transfert `COUNTERPARTY_VASP_NOT_FOUND` ou `COUNTERPARTY_VASP_NOT_REACHABLE` est bloqué, identique à la valeur `reason` du transfert lui-même, afin que la liste permette de distinguer un e-mail de conformité rejeté d'une contrepartie sans routage sans avoir à ouvrir chaque transfert. `\"\"` pour tout autre statut. Voir [Pourquoi un transfert est bloqué](/fr/transaction-monitoring/travel-rule#pourquoi-un-transfert-est-bloqué)."
          },
          "rail": {
            "type": "string",
            "nullable": true,
            "enum": [
              "INTERNAL",
              "TRP",
              "GTR",
              "TRUST",
              "VERIFYVASP",
              "SYGNA",
              "EMAIL",
              "TEST_VASP",
              null
            ]
          },
          "asset": {
            "type": "string",
            "description": "La devise de la transaction."
          },
          "amount": {
            "type": "string",
            "description": "Le montant sous forme décimale simple, par exemple \"1.25\"."
          },
          "originator_vasp": {
            "type": "string",
            "description": "Sortant : la dénomination sociale de votre VASP. Entrant : le nom de la contrepartie, issu de son entrée dans l'annuaire, du membre du réseau Didit, de l'expéditeur TRP, du VASP de test Didit ou du nom déclaré par le transfert. Vide si aucun n'est connu."
          },
          "beneficiary_vasp": {
            "type": "string",
            "description": "Sortant : le nom de la contrepartie, déterminé de la même façon. Entrant : la dénomination sociale de votre VASP."
          },
          "originator_wallet": {
            "type": "string"
          },
          "beneficiary_wallet": {
            "type": "string"
          },
          "originator_memo": {
            "type": "string",
            "description": "Mémo ou balise de destination, vide sur les blockchains qui n'en ont pas."
          },
          "beneficiary_memo": {
            "type": "string"
          },
          "originator_wallet_type": {
            "type": "string",
            "enum": [
              "vasp",
              "self_hosted",
              "own"
            ],
            "description": "vasp, self_hosted (déclaré non hébergé) ou own (un portefeuille que votre carnet d'adresses enregistre comme le vôtre). Votre propre côté est toujours vasp."
          },
          "beneficiary_wallet_type": {
            "type": "string",
            "enum": [
              "vasp",
              "self_hosted",
              "own"
            ]
          },
          "matched_transaction_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "L'autre contrepartie d'un dépôt que vous avez associé manuellement à un transfert annoncé."
          },
          "deadline_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles le transfert expire s'il est toujours en attente de sa contrepartie. Défini sur chaque transfert créé avec `POST /v3/transactions/` nécessitant un échange, sortant ou entrant. Vaut null en dessous du seuil, sur un paiement Lightning auquel la Travel Rule ne s'applique pas, et sur les transferts entrants que Didit crée lorsqu'une contrepartie vous contacte (une demande TRP entrante, un message réseau ou la branche entrante INTERNAL)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BankAccountCheckHolder": {
        "description": "Le nom auquel le compte est comparé. Envoyez exactement l'un des deux champs `full_name` ou `business_name`.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/BankAccountCheckPersonHolder"
          },
          {
            "$ref": "#/components/schemas/BankAccountCheckBusinessHolder"
          }
        ]
      },
      "BankAccountCheckRequest": {
        "type": "object",
        "required": [
          "country",
          "account",
          "holder"
        ],
        "properties": {
          "country": {
            "type": "string",
            "minLength": 3,
            "maxLength": 3,
            "description": "Le pays du compte, sous forme de code ISO 3166-1 alpha-3, par exemple `NGA`. Les minuscules sont acceptées.",
            "example": "NGA"
          },
          "account": {
            "type": "object",
            "description": "Le compte tel qu'écrit dans son pays : un `iban`, ou un `account_number` avec le code de banque ou de branche requis par le pays (`sort_code`, `routing_number`, `transit_institution`, `bsb`, `ifsc`, `bank_code` ou `bic`). Le Mexique utilise un `clabe` et l'Argentine un `cbu_cvu`, qui identifient déjà la banque. Un compte d'entreprise ajoute un `registration_id` lorsque le pays le demande. Les espaces, tirets et points sont ignorés. Les clés non utilisées par la vérification du pays sont ignorées ; une clé requise manquante renvoie un `400` mentionnant son nom.",
            "properties": {
              "iban": {
                "type": "string",
                "maxLength": 64,
                "description": "L'IBAN, dans un pays qui utilise l'IBAN. Il doit appartenir à `country`."
              },
              "account_number": {
                "type": "string",
                "maxLength": 64,
                "description": "Le numéro de compte, dans un pays où le compte s'écrit avec un code de banque ou de branche distinct."
              },
              "sort_code": {
                "type": "string",
                "maxLength": 64,
                "description": "Royaume-Uni : le sort code à 6 chiffres."
              },
              "routing_number": {
                "type": "string",
                "maxLength": 64,
                "description": "États-Unis : le numéro de routage ABA à 9 chiffres."
              },
              "transit_institution": {
                "type": "string",
                "maxLength": 64,
                "description": "Canada : le numéro de transit et d'institution à 8 chiffres."
              },
              "bsb": {
                "type": "string",
                "maxLength": 64,
                "description": "Australie : le BSB à 6 chiffres."
              },
              "ifsc": {
                "type": "string",
                "maxLength": 64,
                "description": "Inde : code IFSC à 11 caractères."
              },
              "bank_code": {
                "type": "string",
                "maxLength": 64,
                "description": "Le code de la banque, lorsque le pays en nécessite un, par exemple au Nigeria."
              },
              "bic": {
                "type": "string",
                "maxLength": 64,
                "description": "Le BIC de la banque, lorsque la vérification du pays en demande un."
              },
              "clabe": {
                "type": "string",
                "maxLength": 64,
                "description": "Mexique : la CLABE à 18 chiffres. Elle indique déjà la banque."
              },
              "cbu_cvu": {
                "type": "string",
                "maxLength": 64,
                "description": "Argentine : le CBU ou CVU à 22 chiffres. Il indique déjà la banque."
              },
              "registration_id": {
                "type": "string",
                "maxLength": 64,
                "description": "Le numéro d'immatriculation d'un compte d'entreprise, lorsque le pays en exige un."
              }
            },
            "additionalProperties": {
              "type": "string",
              "maxLength": 64
            },
            "example": {
              "bank_code": "000014",
              "account_number": "0123450001"
            }
          },
          "holder": {
            "$ref": "#/components/schemas/BankAccountCheckHolder"
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification, renvoyée sans modification.",
            "example": "payout_20481"
          },
          "consent": {
            "type": "boolean",
            "default": false,
            "description": "Définir sur `true` lorsque le titulaire du compte a explicitement consenti à cette vérification. Requis dans les pays où la vérification de compte exige ce consentement : sans lui, la vérification est refusée avec une erreur `400` dont le `field` est `consent` et la `reason` est `required`, et rien n'est facturé. Ailleurs, il est facultatif et Didit l'enregistre avec les frais de la vérification lorsque vous l'envoyez.",
            "example": true
          }
        }
      },
      "BankAccountCheckResponse": {
        "type": "object",
        "required": [
          "request_id",
          "result",
          "holder_name",
          "account",
          "vendor_data",
          "created_at"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "L'identifiant de cette vérification."
          },
          "result": {
            "type": "string",
            "enum": [
              "match",
              "close_match",
              "no_match",
              "cannot_verify"
            ],
            "description": "`match` : la banque détient le compte sous le nom que vous avez envoyé. `close_match` : sous un nom proche, par exemple un deuxième prénom manquant ou une faute de frappe. `no_match` : sous un autre nom, ou ce compte n'existe pas. `cannot_verify` : la banque a répondu sans comparer le nom, par exemple pour un compte bloqué ou clôturé."
          },
          "holder_name": {
            "type": "string",
            "nullable": true,
            "description": "Uniquement sur un `close_match`, et uniquement lorsque la banque l'a renvoyé : le nom figurant sur le compte, tel qu'il figure dans les registres de la banque. `null` sinon."
          },
          "account": {
            "type": "string",
            "description": "Le compte, masqué sauf ses 4 derniers caractères."
          },
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence, telle que vous l'avez envoyée."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure d'exécution de la vérification, en UTC."
          }
        }
      },
      "BankAccountCheckError": {
        "type": "object",
        "required": [
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string",
            "description": "Ce qui s'est mal passé, en anglais."
          },
          "code": {
            "type": "string",
            "description": "Un code stable sur lequel brancher votre logique. Absent sur `401` et `403`."
          },
          "field": {
            "type": "string",
            "description": "`400` uniquement : le champ du corps à corriger, sous forme de chemin avec points, par exemple `account.sort_code`."
          },
          "reason": {
            "type": "string",
            "enum": [
              "required",
              "length",
              "format",
              "checksum",
              "country_mismatch",
              "rejected"
            ],
            "description": "`400` uniquement : raison pour laquelle le champ a été refusé. `required`, `length`, `format`, `checksum` et `country_mismatch` (un IBAN d'un autre pays) sont les propres vérifications de Didit ; `rejected` signifie que la banque a refusé le compte tel qu'envoyé."
          }
        }
      },
      "BankVerificationResult": {
        "type": "object",
        "description": "Résultat d'une étape de vérification bancaire, pour la Vérification des utilisateurs et la Vérification d'entreprise (KYB). `method` indique comment le compte a été vérifié, et `none` que la personne a continué sans banque avant qu'une tentative ne soit évaluée. `continued_without_bank` indique que la personne a continué sans banque, également après une tentative évaluée. Voir [Méthodes de vérification bancaire](/fr/core-technology/bank-verification/verification-methods) et [Lorsque la personne ne peut pas vérifier sa banque](/fr/core-technology/bank-verification/fallbacks).",
        "properties": {
          "schema_version": {
            "type": "integer",
            "description": "Version de ce format de résultat. `1` actuellement."
          },
          "bank_verification_id": {
            "type": "string",
            "format": "uuid",
            "description": "L'identifiant de ce résultat."
          },
          "node_id": {
            "type": "string",
            "description": "Le nœud de workflow auquel ce résultat appartient."
          },
          "status": {
            "type": "string",
            "enum": [
              "Not Finished",
              "Approved",
              "Declined",
              "In Review",
              "Expired"
            ],
            "description": "Le verdict de l'étape, après ses actions et ses règles de statut."
          },
          "original_status": {
            "type": "string",
            "nullable": true,
            "description": "Le premier verdict rendu par l'étape, avant toute modification ultérieure telle qu'un examen manuel."
          },
          "method": {
            "type": "string",
            "nullable": true,
            "enum": [
              "open_banking",
              "account_lookup",
              "microdeposits",
              "statement",
              "none"
            ],
            "description": "Manière dont le compte a été vérifié : `open_banking` (connexion bancaire : la personne s'est connectée auprès de sa banque), `account_lookup` (vérification de compte : la personne a saisi les coordonnées du compte et la banque a confirmé le nom), `microdeposits` ou `statement` (téléversement d'un relevé bancaire). `none` lorsque la personne a poursuivi sans banque avant qu'une tentative n'ait été évaluée, de sorte qu'aucun compte n'a été vérifié. Après une tentative évaluée, la méthode de cette tentative est conservée. `null` jusqu'à ce qu'un compte soit évalué, ainsi que lorsque le workflow restreint les données retournées. Les règles du workflow lisent la même valeur que `bank.method`."
          },
          "provider": {
            "type": "string",
            "nullable": true,
            "description": "La clé de la route qui a exécuté la connexion. Lisez `method`, et non cette clé, pour savoir comment le compte a été vérifié."
          },
          "credential_source": {
            "type": "string",
            "nullable": true,
            "enum": [
              "native",
              "byok"
            ],
            "description": "`native` : la route propre à Didit, facturée sur votre solde Didit. `byok` : un fournisseur de la marketplace que vous avez connecté avec vos propres identifiants."
          },
          "route": {
            "type": "object",
            "nullable": true,
            "description": "La route choisie avant le consentement. Elle ne change jamais par la suite.",
            "properties": {
              "provider_key": {
                "type": "string",
                "nullable": true,
                "description": "La clé de la route."
              },
              "credential_source": {
                "type": "string",
                "enum": [
                  "native",
                  "byok"
                ]
              },
              "is_fallback": {
                "type": "boolean",
                "description": "Indique si la route propre de Didit s'est substituée à un fournisseur de marketplace qui n'a pas pu se connecter."
              },
              "provider_connection_id": {
                "type": "string",
                "nullable": true,
                "description": "La connexion à la marketplace utilisée, pour `byok`."
              },
              "requested_scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Les données demandées par la connexion, par exemple `ownership` ou `balances`."
              }
            }
          },
          "connection": {
            "type": "object",
            "nullable": true,
            "description": "La connexion de la dernière tentative. `null` avant la première tentative.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "connected",
                  "cancelled",
                  "timeout",
                  "failed",
                  "unsupported",
                  "revoked",
                  "expired"
                ]
              },
              "institution_id": {
                "type": "string",
                "nullable": true,
                "description": "L'identifiant de la banque. `null` pour une vérification de compte où aucune banque n'est sélectionnée."
              },
              "institution_name": {
                "type": "string",
                "nullable": true,
                "description": "Le nom de la banque. `null` pour une vérification de compte."
              },
              "institution_country": {
                "type": "string",
                "nullable": true,
                "description": "Le pays du compte, ISO 3166-1 alpha-3."
              },
              "oauth": {
                "type": "boolean",
                "nullable": true,
                "description": "Indique si la connexion bancaire s'est effectuée via OAuth ou via une communication d'application à application. `null` pour une vérification de compte."
              },
              "connected_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure auxquelles la connexion a réussi."
              },
              "consent_expires_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure de fin du consentement bancaire, pour la connexion bancaire."
              },
              "last_refreshed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure de dernière relecture des données financières."
              },
              "attempts": {
                "type": "integer",
                "description": "Le nombre de tentatives que la personne a consacrées à cette étape, toutes méthodes confondues."
              },
              "reason_code": {
                "type": "string",
                "nullable": true,
                "description": "Raison pour laquelle la connexion n'est pas simplement `connected`, par exemple `USER_CANCELLED`, `INSTITUTION_DOWN`, `ACCOUNT_NOT_FOUND`, `REFERENCE_IDENTITY_MISSING` ou `VERIFICATION_COMPLETED`."
              }
            }
          },
          "account": {
            "type": "object",
            "nullable": true,
            "description": "Le compte évalué. `null` jusqu'à ce qu'un compte soit évalué.",
            "properties": {
              "account_id_masked": {
                "type": "string",
                "nullable": true,
                "description": "Le numéro de compte, masqué."
              },
              "iban_masked": {
                "type": "string",
                "nullable": true,
                "description": "L'IBAN, masqué."
              },
              "sort_code": {
                "type": "string",
                "nullable": true,
                "description": "Le code guichet, au Royaume-Uni."
              },
              "routing_number_masked": {
                "type": "string",
                "nullable": true,
                "description": "Le numéro de routage, masqué."
              },
              "type": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "checking",
                  "current",
                  "savings",
                  "business",
                  "other"
                ]
              },
              "subtype": {
                "type": "string",
                "nullable": true,
                "description": "Le sous-type de compte propre à la banque."
              },
              "currency": {
                "type": "string",
                "nullable": true,
                "description": "Devise ISO 4217 du compte."
              },
              "holder_type": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "person",
                  "business",
                  "unknown"
                ]
              },
              "holders_count": {
                "type": "integer",
                "nullable": true
              },
              "is_joint": {
                "type": "boolean",
                "nullable": true
              },
              "is_business": {
                "type": "boolean",
                "nullable": true
              }
            }
          },
          "ownership": {
            "type": "object",
            "nullable": true,
            "description": "Manière dont le titulaire du compte a été comparé à l'identité vérifiée. `null` jusqu'à ce qu'un compte soit évalué.",
            "properties": {
              "result": {
                "type": "string",
                "enum": [
                  "match",
                  "partial_match",
                  "no_match",
                  "unknown",
                  "not_verifiable"
                ],
                "description": "`partial_match` indique une correspondance proche. `not_verifiable` : la banque a répondu sans titulaire à comparer. `unknown` : la pièce justificative n'a pas pu être lue, ou il n'y avait aucune identité à comparer."
              },
              "reference_identity_source": {
                "type": "string",
                "nullable": true,
                "description": "L'étape par rapport à laquelle l'identité du titulaire a été comparée : `kyc`, `database_validation`, `expected_details`, `questionnaire`, `document_ai` ou `kyb`."
              },
              "name_score": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "nullable": true,
                "description": "Score Didit du nom du titulaire."
              },
              "provider_name_score": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "nullable": true,
                "description": "Le score du nom du titulaire propre à la banque, lorsqu'elle en a renvoyé un."
              },
              "address_score": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "nullable": true,
                "description": "Le score de l'adresse du titulaire, lorsque la correspondance d'adresse a été effectuée."
              },
              "email_score": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "nullable": true,
                "description": "Le score de l'e-mail du titulaire, lorsque la correspondance d'e-mail a été effectuée."
              },
              "phone_score": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "nullable": true,
                "description": "Le score du téléphone du titulaire, lorsque la correspondance de téléphone a été effectuée."
              },
              "dob_score": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100,
                "nullable": true,
                "description": "Le score de la date de naissance du titulaire, lorsque la banque en a partagé une."
              },
              "close_match": {
                "type": "boolean",
                "nullable": true,
                "description": "Indique si le nom se situe dans la plage de correspondance proche."
              },
              "holder_confirmation": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "pending",
                  "confirmed",
                  "rejected"
                ],
                "description": "La réponse de la personne lorsqu'il lui est demandé de confirmer un nom très proche. `null` si aucune demande n'a été formulée."
              },
              "method": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "exact",
                  "token_set",
                  "nickname",
                  "transliteration",
                  "fuzzy",
                  "provider_only",
                  "microdeposits"
                ],
                "description": "Quelle comparaison de noms a produit le score. Il ne s'agit pas de la méthode de vérification : consultez le champ de premier niveau `method` pour cela."
              },
              "matched_holder_index": {
                "type": "integer",
                "nullable": true
              },
              "holders": {
                "type": "array",
                "items": {
                  "type": "object"
                },
                "description": "Chaque titulaire répertorié par la banque, avec ses scores."
              },
              "owner_identity_available": {
                "type": "boolean",
                "nullable": true
              },
              "evidence_freshness": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "live",
                  "cached",
                  "refreshed"
                ]
              },
              "evaluated_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Date et heure auxquelles la décision a été calculée."
              }
            }
          },
          "financial_data": {
            "type": "object",
            "description": "Les données financières lues par l'étape. Seule la connexion bancaire les lit.",
            "properties": {
              "balances": {
                "type": "object",
                "nullable": true,
                "description": "Avec la portée `balances`."
              },
              "transactions": {
                "type": "object",
                "nullable": true,
                "description": "Avec la portée `transactions`."
              },
              "income": {
                "type": "object",
                "nullable": true,
                "description": "Avec la portée `income`."
              },
              "categorization": {
                "type": "object",
                "nullable": true,
                "description": "Catégorisation par Didit des transactions lues. `null` lorsqu'il n'y en a pas."
              },
              "not_collected": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "balances",
                    "income",
                    "transactions"
                  ]
                },
                "description": "Les données demandées par l'étape que la méthode ayant vérifié le compte ne collecte pas. Les soldes, transactions et revenus proviennent uniquement de la connexion bancaire, donc un compte vérifié par vérification de compte les répertorie ici. Jamais un échec. Vide sinon."
              }
            }
          },
          "billing": {
            "type": "object",
            "nullable": true,
            "properties": {
              "route": {
                "type": "string",
                "enum": [
                  "native",
                  "byok"
                ]
              },
              "billed": {
                "type": "boolean"
              },
              "marketplace_fee": {
                "type": "string",
                "nullable": true,
                "description": "Les frais de plateforme de la marketplace facturés, pour `byok`."
              },
              "usage_type": {
                "type": "string",
                "nullable": true,
                "description": "La ligne d'utilisation sur laquelle le débit a été comptabilisé : `bank_verification` pour une connexion bancaire ou une vérification de compte, `bank_statement_upload` pour un téléversement de relevé sans tentative bancaire facturée préalable, et `bank_byok_fee` pour les frais de marketplace sur votre propre fournisseur. `null` lorsque rien n'a été facturé."
              }
            }
          },
          "reference_identity": {
            "type": "object",
            "nullable": true,
            "description": "L'identité à laquelle le titulaire a été comparé, avec sa source."
          },
          "signals": {
            "type": "object",
            "nullable": true,
            "description": "Signaux du compte lus à partir de l'historique des transactions, lorsque l'étape en a lu un."
          },
          "connection_abandoned": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si l'étape s'est terminée sans correspondance après que la personne a quitté l'étape auprès de sa banque."
          },
          "not_covered": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si la banque ou le pays de la personne n'a pas pu être joint lors de cette étape. Vaut également `true` lorsque la personne a continué sans banque parce qu'aucune méthode n'a pu vérifier son pays ou sa banque."
          },
          "continued_without_bank": {
            "type": "boolean",
            "description": "Indique si la personne a quitté l'étape avec **Continuer sans votre banque**. `continuation` indique alors la raison. `method` vaut `none` lorsqu'aucune tentative n'a été évaluée avant qu'elle ne continue. Après une tentative évaluée, comme un titulaire ne correspondant pas, `method` conserve la méthode de cette tentative et son verdict ainsi que ses codes de motif sont maintenus. Renvoyé même lorsque le workflow restreint les données qu'il retourne."
          },
          "continuation": {
            "type": "object",
            "nullable": true,
            "description": "Manière dont la personne a poursuivi sans banque. `null` lorsqu'elle ne l'a pas fait. Lorsque le workflow restreint les données retournées, `reason` est toujours renvoyé et toutes les autres clés sont `null`.",
            "properties": {
              "reason": {
                "type": "string",
                "enum": [
                  "no_route",
                  "institution_unsupported",
                  "attempts_exhausted",
                  "person_choice"
                ],
                "description": "Raison, telle que Didit l'a déterminée lorsque la personne a poursuivi : `no_route` (aucune connexion bancaire ni vérification de compte ne dessert son pays), `institution_unsupported` (la banque sélectionnée ne peut pas être utilisée sur cette étape), `attempts_exhausted` (toutes les tentatives étaient déjà épuisées et aucune n'était en cours) ou `person_choice` (un moyen de vérification était disponible et elle a choisi de poursuivre, y compris lorsque sa banque n'était pas joignable à cet instant). `no_route` et `institution_unsupported` suivent `bank_unsupported_action`, `attempts_exhausted` suit `bank_attempts_exhausted_action`, et `person_choice` suit `bank_skipped_action`, à moins qu'une tentative évaluée n'ait déjà tranché l'étape."
              },
              "country": {
                "type": "string",
                "nullable": true,
                "description": "Le pays dans lequel la personne effectuait la vérification, au format ISO 3166-1 alpha-3. `null` si elle a continué avant d'en sélectionner un."
              },
              "offered": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "statement",
                    "microdeposits"
                  ]
                },
                "nullable": true,
                "description": "Les autres moyens de vérification proposés à la personne par ce pays lorsqu'elle a continué, dans l'ordre où ils ont été proposés : `statement` (téléversement d'un relevé), puis `microdeposits`. Vide si aucun n'a été proposé."
              },
              "institution_id": {
                "type": "string",
                "nullable": true,
                "description": "Pour `institution_unsupported`, l'identifiant de la banque que la personne n'a pas pu utiliser : la banque qu'elle a sélectionnée ou celle sur laquelle sa dernière tentative s'est terminée. Didit le tire de sa propre liste de banques, jamais de l'appareil de la personne, donc une banque absente de cette liste est `null`. `null` pour tout autre motif."
              },
              "institution_name": {
                "type": "string",
                "nullable": true,
                "description": "Pour `institution_unsupported`, le nom de cette banque, issu de la même liste que `institution_id`. `null` lorsque cette liste ne comporte pas la banque, et pour tout autre motif."
              },
              "continued_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Moment où la personne a poursuivi."
              }
            }
          },
          "evidence_purged_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles la preuve bancaire a été supprimée conformément à `bank_evidence_retention_days`. `null` sinon."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Codes informatifs, par exemple `holder_declared`. Un avertissement ne modifie jamais le statut à lui seul."
          },
          "reason_codes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Raison pour laquelle le verdict a été rendu ainsi, par exemple `OWNER_NAME_PARTIAL`. Plusieurs raisons peuvent s'appliquer. `NOT_COVERED` : la personne a continué sans banque car aucune méthode ne pouvait vérifier son pays ou sa banque. `SKIPPED` : la personne a choisi de continuer sans banque alors qu'un moyen de vérification était disponible. Aucun des deux n'est ajouté lorsqu'une tentative évaluée a déjà tranché l'étape."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BankAccountCheckPersonHolder": {
        "type": "object",
        "description": "La personne qui doit détenir le compte.",
        "required": [
          "full_name"
        ],
        "properties": {
          "full_name": {
            "type": "string",
            "maxLength": 255,
            "description": "Le nom complet de la personne qui doit détenir le compte.",
            "example": "Maria Oliveira"
          }
        }
      },
      "BankAccountCheckBusinessHolder": {
        "type": "object",
        "description": "L'entreprise qui doit détenir le compte. Vérifie un compte professionnel.",
        "required": [
          "business_name"
        ],
        "properties": {
          "business_name": {
            "type": "string",
            "maxLength": 255,
            "description": "Le nom de l'entreprise qui doit détenir le compte. Vérifie un compte d'entreprise."
          }
        }
      },
      "BankVerificationPricing": {
        "type": "object",
        "description": "Tarifs publics pour la vérification bancaire : le téléversement de relevé, les frais liés à votre propre clé de fournisseur et les méthodes de chaque pays.",
        "required": [
          "currency",
          "statement_upload",
          "own_provider_fee_usd",
          "countries"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ],
            "description": "Devise de chaque prix dans la réponse.",
            "example": "USD"
          },
          "statement_upload": {
            "$ref": "#/components/schemas/BankStatementUploadPricing"
          },
          "own_provider_fee_usd": {
            "type": "string",
            "description": "Frais pour chaque vérification d'actionnariat facturable sur un routage utilisant votre propre contrat de fournisseur au lieu de celui de Didit, facturés quel que soit le résultat. Une connexion annulée, expirée par dépassement de délai ou abandonnée n'est pas facturée. Chaîne décimale avec 4 décimales, en USD.",
            "example": "0.0200"
          },
          "countries": {
            "type": "object",
            "description": "Chaque pays, indexé par son code ISO 3166-1 alpha-3.",
            "additionalProperties": {
              "$ref": "#/components/schemas/BankVerificationPricingCountry"
            }
          }
        }
      },
      "BankStatementUploadPricing": {
        "type": "object",
        "description": "Manière dont le téléversement de relevé bancaire est facturé.",
        "required": [
          "price_usd",
          "included_after_charged_bank_attempt",
          "standalone_available"
        ],
        "properties": {
          "price_usd": {
            "type": "string",
            "description": "Prix du téléversement d'un relevé après une tentative bancaire facturée. Chaîne décimale avec 4 décimales, en USD.",
            "example": "0.0000"
          },
          "included_after_charged_bank_attempt": {
            "type": "boolean",
            "description": "`true` lorsque le téléversement est inclus sans frais supplémentaires après une tentative bancaire facturée dans la même session.",
            "example": true
          },
          "standalone_available": {
            "type": "boolean",
            "description": "`true` lorsqu'un téléversement de relevé peut s'exécuter seul, sans tentative bancaire préalable. `false` en production ; les sessions en sandbox peuvent le tester sans facturation.",
            "example": false
          }
        }
      },
      "BankVerificationPricingCountry": {
        "type": "object",
        "description": "Les méthodes de vérification bancaire d'un pays et leurs prix catalogue.",
        "required": [
          "name",
          "methods"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nom du pays en anglais.",
            "example": "United Kingdom"
          },
          "methods": {
            "$ref": "#/components/schemas/BankVerificationPricingMethods"
          }
        }
      },
      "BankVerificationPricingMethods": {
        "type": "object",
        "description": "Les deux méthodes de vérification bancaire dans un pays.",
        "required": [
          "open_banking",
          "account_lookup"
        ],
        "properties": {
          "open_banking": {
            "$ref": "#/components/schemas/BankSignInPricing"
          },
          "account_lookup": {
            "$ref": "#/components/schemas/BankAccountCheckPricing"
          }
        }
      },
      "BankSignInPricing": {
        "type": "object",
        "description": "Connexion bancaire : la personne se connecte à sa banque. Facturée par marché, identique pour chaque banque de ce marché.",
        "required": [
          "available",
          "market",
          "price_usd",
          "add_ons"
        ],
        "properties": {
          "available": {
            "type": "boolean",
            "description": "`true` uniquement là où Didit prend en charge la connexion bancaire dans ce pays en production.",
            "example": true
          },
          "market": {
            "type": "string",
            "nullable": true,
            "description": "Le marché dont le prix s'applique. `null` lorsqu'il n'est pas disponible.",
            "example": "UK and EEA"
          },
          "price_usd": {
            "type": "string",
            "nullable": true,
            "description": "Prix catalogue d'une connexion bancaire. `null` lorsqu'il n'est pas disponible. Chaîne décimale avec 4 décimales, en USD.",
            "example": "0.7900"
          },
          "add_ons": {
            "type": "object",
            "description": "Options supplémentaires tarifiées dans ce pays, chacune sous forme de chaîne décimale à 4 décimales en USD, ajoutées au prix de la connexion bancaire. Seules les options proposées par le pays sont listées ; vide lorsque la connexion bancaire n'est pas disponible.",
            "properties": {
              "balance": {
                "type": "string",
                "description": "Module complémentaire de solde de compte.",
                "example": "0.3500"
              },
              "transactions": {
                "type": "string",
                "description": "Module complémentaire Transactions.",
                "example": "1.3000"
              }
            }
          }
        }
      },
      "BankAccountCheckPricing": {
        "type": "object",
        "description": "Vérification de compte : la personne saisit son numéro de compte et Didit le vérifie auprès de la banque. Tarification par pays.",
        "required": [
          "available",
          "price_usd"
        ],
        "properties": {
          "available": {
            "type": "boolean",
            "description": "`true` uniquement là où Didit propose la vérification de compte dans ce pays en production.",
            "example": true
          },
          "price_usd": {
            "type": "string",
            "nullable": true,
            "description": "Prix catalogue d'une vérification de compte répondue par la banque. `null` lorsqu'il n'est pas disponible. Chaîne décimale avec 4 décimales, en USD.",
            "example": "0.4000"
          }
        }
      },
      "ImportProvider": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "enum": [
              "sumsub",
              "jumio",
              "veriff",
              "onfido",
              "persona",
              "metamap",
              "socure",
              "idnow",
              "shufti",
              "idenfy",
              "ondato",
              "trulioo",
              "au10tix",
              "complycube",
              "other"
            ]
          },
          "name": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "api_list",
              "api_ids",
              "export_file"
            ],
            "description": "`api_list` : Didit liste les enregistrements avec la clé. `api_ids` : téléversez les ID d'enregistrement depuis un export. `export_file` : téléversez un export au format de Didit."
          },
          "record_noun": {
            "type": "string"
          },
          "credential_fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "secret": {
                  "type": "boolean"
                }
              }
            }
          },
          "regions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "required_permissions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "docs_url": {
            "type": "string",
            "nullable": true
          },
          "status_mapping": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "enum": [
                "Approved",
                "Declined",
                "In Review",
                "Expired",
                "Not Finished",
                "Abandoned"
              ]
            }
          }
        }
      },
      "ImportJobSummary": {
        "type": "object",
        "description": "Une tâche d'importation de n'importe quel type, sous la structure lue par le volet Tâches d'importation de la console.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "sessions",
              "businesses",
              "users",
              "status_rules",
              "transactions"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "file",
              "api",
              "provider"
            ]
          },
          "provider": {
            "type": "string",
            "nullable": true
          },
          "provider_name": {
            "type": "string",
            "nullable": true
          },
          "filename": {
            "type": "string",
            "nullable": true
          },
          "state": {
            "type": "string",
            "enum": [
              "ready",
              "queued",
              "running",
              "paused",
              "completed",
              "errors",
              "failed",
              "cancelled"
            ],
            "description": "L'état de la tâche tel qu'affiché dans la console ; `errors` correspond à une tâche terminée avec des lignes rejetées."
          },
          "status": {
            "type": "string"
          },
          "is_dry_run": {
            "type": "boolean"
          },
          "credential_hint": {
            "type": "string",
            "nullable": true
          },
          "resumes_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_error": {
            "type": "string",
            "nullable": true
          },
          "started_by": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "nullable": true
              },
              "email": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "progress": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "format": "int64"
              },
              "processed": {
                "type": "integer",
                "format": "int64"
              },
              "imported": {
                "type": "integer",
                "format": "int64"
              },
              "updated": {
                "type": "integer",
                "format": "int64"
              },
              "already_in_didit": {
                "type": "integer",
                "format": "int64"
              },
              "failed": {
                "type": "integer",
                "format": "int64"
              },
              "not_finished": {
                "type": "integer",
                "format": "int64"
              },
              "same_person": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          "face_templates": {
            "type": "object",
            "nullable": true,
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "built": {
                "type": "integer",
                "format": "int64"
              },
              "duplicates": {
                "type": "integer",
                "format": "int64"
              },
              "blocklisted": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          "eta_seconds": {
            "type": "integer",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "FiledRegulatoryReport": {
        "type": "object",
        "description": "Un rapport réglementaire finalisé qui empêche la suppression demandée.",
        "required": [
          "uuid",
          "report_number",
          "report_type",
          "case_uuid"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID du rapport."
          },
          "report_number": {
            "type": "string",
            "description": "Numéro de rapport affiché dans la Console (par exemple, SAR-0001)."
          },
          "report_type": {
            "type": "string",
            "enum": [
              "SAR",
              "STR",
              "CTR",
              "TTR",
              "UTR",
              "IFT",
              "CBR",
              "TFR"
            ],
            "description": "Type de rapport réglementaire."
          },
          "case_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Dossier auquel appartient le rapport."
          }
        }
      },
      "FiledReportTransaction": {
        "type": "object",
        "description": "Une transaction qui ne peut pas être supprimée car un rapport réglementaire finalisé la répertorie.",
        "required": [
          "uuid",
          "transaction_id",
          "reports"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID de transaction Didit."
          },
          "transaction_id": {
            "type": "string",
            "description": "L'identifiant de la transaction fourni lors de la création de la transaction."
          },
          "reports": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FiledRegulatoryReport"
            },
            "description": "Rapports finalisés répertoriant cette transaction."
          }
        }
      },
      "InFiledReportError": {
        "type": "object",
        "description": "La suppression est refusée car les données sélectionnées figurent dans un rapport réglementaire finalisé. Rien n'est supprimé. Supprimez le rapport, puis réessayez la requête.",
        "required": [
          "detail",
          "code"
        ],
        "properties": {
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "in_filed_report"
            ],
            "description": "Code d'erreur stable pour une suppression bloquée par un rapport réglementaire finalisé."
          },
          "reports": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FiledRegulatoryReport"
            },
            "description": "Rapports qui bloquent la suppression d'une personne, d'une entreprise, d'un dossier ou d'une session."
          },
          "transactions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FiledReportTransaction"
            },
            "description": "Transactions qui bloquent la suppression d'une transaction, chacune accompagnée des rapports qui la répertorient."
          }
        }
      },
      "SubjectDeletionInProgressError": {
        "type": "object",
        "description": "Une autre requête est toujours en train de supprimer cette personne ou cette entreprise. Cette requête n'a rien supprimé et peut être réessayée une fois cette suppression terminée ; une nouvelle tentative supprimera alors ce qui est encore sélectionné.",
        "required": [
          "detail",
          "code"
        ],
        "properties": {
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "subject_deletion_in_progress"
            ],
            "description": "Code d'erreur stable pour une personne ou une entreprise qu'une autre requête est toujours en train de supprimer."
          }
        }
      },
      "TravelRuleNetworkParticipantSummary": {
        "type": "object",
        "nullable": true,
        "description": "Le participant propre à cette application sur le réseau, ou null lorsqu'elle n'en a aucun.",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "platform",
              "own"
            ],
            "description": "platform : pris en charge par l'adhésion de Didit ; own : onboardé sous la propre adhésion de l'application."
          },
          "status": {
            "type": "string",
            "enum": [
              "not_requested",
              "questionnaire_pending",
              "submitted_to_network",
              "active",
              "suspended",
              "rejected"
            ],
            "description": "not_requested : jamais demandé, ou le réseau a refusé la première demande (voir last_error) ; questionnaire_pending : en attente de l'approbation du questionnaire de diligence raisonnable ; submitted_to_network : transmis à l'onboarding du réseau ; active : le réseau a attribué à cette application son propre code de participant ; suspended / rejected : Didit l'a suspendue ou rejetée."
          },
          "participant_code": {
            "type": "string",
            "description": "Le code attribué par le réseau à cette application (pour GTR, son code VASP). Les messages sortants portent ce code, jamais celui de Didit."
          },
          "requested_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "activated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_error": {
            "type": "string",
            "description": "La réponse du réseau lorsqu'il a refusé l'enregistrement ; vide dans le cas contraire."
          }
        }
      },
      "TravelRuleNetworkState": {
        "type": "object",
        "description": "Manière dont les messages Travel Rule sur un réseau seraient envoyés pour cette application, et pourquoi ils ne peuvent pas l'être. Statut de configuration, et non vérification en direct de l'état ou de la livraison.",
        "properties": {
          "rail": {
            "type": "string",
            "enum": [
              "GTR",
              "TRUST",
              "VERIFYVASP",
              "SYGNA"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "own",
              "didit",
              "off",
              "unavailable"
            ],
            "description": "own : l'adhésion connectée de l'application est utilisée ; didit : l'adhésion de Didit intègre l'application en tant que participant actif propre ; off : routage de la plateforme désactivé dans disabled_networks sans adhésion propre ; unavailable : rien ne peut être envoyé sur ce réseau pour le moment (voir state et reason)."
          },
          "state": {
            "type": "string",
            "enum": [
              "own_membership",
              "live_through_didit",
              "off",
              "didit_onboarding",
              "questionnaire_needed",
              "questionnaire_in_review",
              "request_access",
              "request_sent",
              "unavailable",
              "error"
            ],
            "description": "own_membership : votre adhésion connectée effectue l'envoi ; live_through_didit : votre propre participant rattaché à l'adhésion de Didit effectue l'envoi ; off : vous avez désactivé le routage de la plateforme ; didit_onboarding : la propre adhésion de Didit à ce réseau n'est pas encore active, elle ne peut donc intégrer personne ; questionnaire_needed / questionnaire_in_review : le questionnaire de diligence raisonnable doit être soumis ou est en cours d'examen par Didit ; request_access : le questionnaire est approuvé, faites la demande auprès du réseau ; request_sent : votre participant est en cours d'onboarding ; unavailable : voir reason ; error : voir reason."
          },
          "reason": {
            "type": "string",
            "enum": [
              "own_membership_connected",
              "platform_network_switched_off",
              "own_membership_only",
              "sandbox_application",
              "didit_membership_not_live",
              "participant_suspended",
              "participant_rejected",
              "questionnaire_not_submitted",
              "questionnaire_submitted",
              "questionnaire_changes_requested",
              "questionnaire_rejected",
              "participant_not_requested",
              "participant_active",
              "participant_key_missing",
              "participant_key_unresolved",
              "provisioning_failed",
              "questionnaire_pending",
              "submitted_to_network"
            ],
            "description": "Détail de l'état lisible par machine. own_membership_only : Didit n'a pas d'application sur ce réseau (TRUST) ; connectez votre propre adhésion ; sandbox_application : les transferts sandbox n'atteignent jamais un réseau ; provisioning_failed : le réseau a refusé l'inscription, le last_error du participant en indique la raison et effectuer une nouvelle demande auprès du réseau permet de réessayer."
          },
          "platform_available": {
            "type": "boolean",
            "description": "Indique si l'adhésion propre de Didit à ce réseau est configurée ; il ne s'agit pas d'une vérification de l'état en direct."
          },
          "connected": {
            "type": "boolean",
            "description": "Indique s'il existe une adhésion client connectée. Les identifiants sont validés localement ; la validation réseau a lieu sur un échange en direct."
          },
          "participant": {
            "$ref": "#/components/schemas/TravelRuleNetworkParticipantSummary"
          },
          "vasps_reachable": {
            "type": "integer",
            "description": "VASP de l'annuaire joignables sur ce réseau."
          },
          "routed_30d": {
            "type": "integer",
            "description": "Les transferts de cette application acheminés sur ce réseau au cours des 30 derniers jours."
          }
        }
      },
      "TravelRuleNetworkQuestionnaireAnswers": {
        "type": "object",
        "description": "Questionnaire de diligence raisonnable de réseau de Didit. Les enregistrements sont partiels : un enregistrement conserve chaque réponse qu'il ne nomme pas. La soumission requiert tous les champs sauf lei et data_protection_contact_email, ainsi que les trois attestations à vrai.",
        "properties": {
          "legal_name": {
            "type": "string",
            "maxLength": 255
          },
          "registration_number": {
            "type": "string",
            "maxLength": 255
          },
          "incorporation_country": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "Code pays ISO 3166-1 alpha-2."
          },
          "registered_address": {
            "type": "string",
            "maxLength": 1000
          },
          "website": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "lei": {
            "type": "string",
            "maxLength": 20,
            "description": "Optionnel. Un LEI ISO 17442 valide lorsqu'il est renseigné."
          },
          "licences": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": [
                "regulator",
                "jurisdiction",
                "licence_type",
                "licence_number"
              ],
              "properties": {
                "regulator": {
                  "type": "string",
                  "maxLength": 255
                },
                "jurisdiction": {
                  "type": "string",
                  "minLength": 2,
                  "maxLength": 2,
                  "description": "Code pays ISO 3166-1 alpha-2."
                },
                "licence_type": {
                  "type": "string",
                  "maxLength": 255
                },
                "licence_number": {
                  "type": "string",
                  "maxLength": 255
                }
              }
            },
            "description": "Chaque licence ou immatriculation détenue par le VASP."
          },
          "operating_jurisdictions": {
            "type": "array",
            "minItems": 1,
            "maxItems": 250,
            "items": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2,
              "description": "Code pays ISO 3166-1 alpha-2."
            }
          },
          "compliance_officer_name": {
            "type": "string",
            "maxLength": 255
          },
          "compliance_officer_email": {
            "type": "string",
            "format": "email"
          },
          "aml_ctf_policy_attested": {
            "type": "boolean",
            "description": "Doit être vrai pour soumettre."
          },
          "sanctions_screening_attested": {
            "type": "boolean",
            "description": "Doit être vrai pour soumettre."
          },
          "data_protection_attested": {
            "type": "boolean",
            "description": "Doit être vrai pour soumettre."
          },
          "data_protection_contact_email": {
            "type": "string",
            "format": "email",
            "description": "Optionnel."
          },
          "expected_monthly_transfers": {
            "type": "integer",
            "minimum": 0
          },
          "expected_monthly_volume_usd": {
            "type": "string",
            "format": "decimal",
            "description": "Volume mensuel attendu en USD, jusqu'à 2 décimales. Renvoyé sous forme de chaîne."
          },
          "assets": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "type": "string",
              "maxLength": 32
            },
            "description": "Tickers d'actifs, stockés en majuscules, triés et dédupliqués."
          }
        }
      },
      "TravelRuleNetworkQuestionnaire": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "submitted",
              "changes_requested",
              "approved",
              "rejected"
            ],
            "description": "Les réponses peuvent être enregistrées lorsqu'elles sont à l'état draft ou changes_requested ; le passage à submitted, approved et rejected revient à Didit."
          },
          "answers": {
            "$ref": "#/components/schemas/TravelRuleNetworkQuestionnaireAnswers"
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "reviewed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "review_note": {
            "type": "string",
            "description": "Note de Didit sur sa dernière décision, par exemple les éléments à modifier."
          },
          "history": {
            "type": "array",
            "readOnly": true,
            "description": "Chaque changement de statut, du plus ancien au plus récent.",
            "items": {
              "type": "object",
              "properties": {
                "at": {
                  "type": "string",
                  "format": "date-time"
                },
                "from": {
                  "type": "string"
                },
                "to": {
                  "type": "string"
                },
                "note": {
                  "type": "string",
                  "description": "Note d'examen ou réponse du réseau, le cas échéant."
                }
              }
            }
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "TravelRuleNetworkParticipant": {
        "type": "object",
        "description": "Le participant propre à cette application sur un réseau.",
        "properties": {
          "network": {
            "type": "string",
            "enum": [
              "gtr",
              "trust",
              "verifyvasp",
              "sygna"
            ]
          },
          "rail": {
            "type": "string",
            "enum": [
              "GTR",
              "TRUST",
              "VERIFYVASP",
              "SYGNA"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "platform",
              "own"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "not_requested",
              "questionnaire_pending",
              "submitted_to_network",
              "active",
              "suspended",
              "rejected"
            ],
            "description": "not_requested : jamais demandé, ou le réseau a refusé la première demande (voir last_error) ; questionnaire_pending : en attente de l'approbation du questionnaire de diligence raisonnable ; submitted_to_network : transmis à l'onboarding du réseau ; active : le réseau a attribué à cette application son propre code de participant ; suspended / rejected : Didit l'a suspendue ou rejetée."
          },
          "participant_code": {
            "type": "string"
          },
          "requested_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "activated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "suspended_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_error": {
            "type": "string",
            "description": "La réponse du réseau lorsqu'il a refusé l'enregistrement ; vide dans le cas contraire."
          },
          "history": {
            "type": "array",
            "readOnly": true,
            "description": "Chaque changement de statut, du plus ancien au plus récent.",
            "items": {
              "type": "object",
              "properties": {
                "at": {
                  "type": "string",
                  "format": "date-time"
                },
                "from": {
                  "type": "string"
                },
                "to": {
                  "type": "string"
                },
                "note": {
                  "type": "string",
                  "description": "Note d'examen ou réponse du réseau, le cas échéant."
                }
              }
            }
          }
        }
      },
      "TravelRuleNetworksOverview": {
        "type": "object",
        "properties": {
          "platform_networks_enabled": {
            "type": "boolean",
            "description": "Indique si l'accès au réseau via l'adhésion de Didit est ouvert. Tant qu'il est défini sur false, les sauvegardes de questionnaires, les soumissions et les requêtes réseau répondent par un code 403."
          },
          "questionnaire": {
            "$ref": "#/components/schemas/TravelRuleNetworkQuestionnaire"
          },
          "participants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TravelRuleNetworkParticipant"
            }
          },
          "networks": {
            "type": "object",
            "readOnly": true,
            "description": "Par réseau, comment cette application enverrait et pourquoi elle ne le peut pas. Aucun réseau, y compris GTR, n'est inclus par défaut : un réseau est accessible via votre propre adhésion connectée, ou via l'adhésion de Didit une fois que l'adhésion de Didit à ce réseau est active et que votre propre participant y est actif. Il ne s'agit pas d'une vérification de l'état ou de la livraison en direct.",
            "properties": {
              "gtr": {
                "$ref": "#/components/schemas/TravelRuleNetworkState"
              },
              "trust": {
                "$ref": "#/components/schemas/TravelRuleNetworkState"
              },
              "verifyvasp": {
                "$ref": "#/components/schemas/TravelRuleNetworkState"
              },
              "sygna": {
                "$ref": "#/components/schemas/TravelRuleNetworkState"
              }
            }
          }
        }
      },
      "AddressValidationResult": {
        "type": "object",
        "description": "Le résultat d'une Address Validation : indique si l'adresse existe, ainsi que sa forme normalisée. Cela confirme uniquement l'adresse ; cela ne lie jamais l'adresse à une personne.",
        "required": [
          "status",
          "verification_level",
          "address",
          "formatted_address",
          "latitude",
          "longitude"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "verified",
              "partially_verified",
              "not_verified",
              "unavailable"
            ],
            "description": "`verified` : l'adresse a été confirmée jusqu'au bâtiment (ou à l'appartement ou à la boîte postale). `partially_verified` : elle a été confirmée uniquement jusqu'à la rue, ou au niveau le plus précis contenu dans les données de référence postales pour ce lieu. `not_verified` : seule la région ou la ville correspondait, ou rien ne correspondait. `unavailable` : la validation n'a pas pu être exécutée (par exemple, le service de référence n'a pas répondu) ; elle n'est pas facturée et n'affecte jamais une vérification."
          },
          "verification_level": {
            "type": "string",
            "nullable": true,
            "enum": [
              "administrative_area",
              "locality",
              "thoroughfare",
              "premise",
              "delivery_point",
              null
            ],
            "description": "Le niveau le plus précis auquel l'adresse a été mise en correspondance. `null` si aucune correspondance n'a été trouvée ou si `status` est `unavailable`."
          },
          "address": {
            "type": "object",
            "nullable": true,
            "description": "L'adresse normalisée. `null` lorsque `status` est `unavailable`.",
            "properties": {
              "address_line_1": {
                "type": "string",
                "nullable": true,
                "description": "Première ligne de livraison, rédigée selon le format du pays.",
                "example": "1600 Amphitheatre Pkwy"
              },
              "address_line_2": {
                "type": "string",
                "nullable": true,
                "description": "Deuxième ligne de livraison (appartement, bâtiment ou quartier), si l'adresse en comporte une."
              },
              "city": {
                "type": "string",
                "nullable": true,
                "example": "Mountain View"
              },
              "region": {
                "type": "string",
                "nullable": true,
                "description": "État, province ou région.",
                "example": "CA"
              },
              "postal_code": {
                "type": "string",
                "nullable": true,
                "example": "94043-1351"
              },
              "country": {
                "type": "string",
                "nullable": true,
                "description": "Code pays ISO 3166-1 alpha-2.",
                "example": "US"
              }
            }
          },
          "formatted_address": {
            "type": "string",
            "nullable": true,
            "description": "L'adresse normalisée sur une seule ligne.",
            "example": "1600 Amphitheatre Pkwy, Mountain View CA 94043-1351"
          },
          "latitude": {
            "type": "number",
            "nullable": true,
            "example": 37.422022
          },
          "longitude": {
            "type": "number",
            "nullable": true,
            "example": -122.08429
          }
        }
      },
      "AddressValidationRequest": {
        "type": "object",
        "required": [
          "country"
        ],
        "description": "Une adresse : sur une seule ligne (`address`) ou sous forme de champs structurés avec au moins `address_line_1`, jamais les deux.",
        "properties": {
          "address": {
            "type": "string",
            "maxLength": 500,
            "description": "L'adresse complète sur une seule ligne.",
            "example": "Paseo de la Castellana 259, 28046 Madrid"
          },
          "address_line_1": {
            "type": "string",
            "maxLength": 255,
            "description": "Rue et numéro.",
            "example": "1600 Amphitheatre Pkwy"
          },
          "address_line_2": {
            "type": "string",
            "maxLength": 255,
            "description": "Appartement, suite, étage ou bâtiment."
          },
          "city": {
            "type": "string",
            "maxLength": 128,
            "description": "Ville ou localité.",
            "example": "Mountain View"
          },
          "region": {
            "type": "string",
            "maxLength": 128,
            "description": "État, province ou région.",
            "example": "CA"
          },
          "postal_code": {
            "type": "string",
            "maxLength": 32,
            "example": "94043"
          },
          "country": {
            "type": "string",
            "maxLength": 3,
            "description": "Code ISO 3166-1 alpha-2 ou alpha-3 du pays de l'adresse.",
            "example": "US"
          }
        }
      },
      "AddressValidationResponse": {
        "type": "object",
        "required": [
          "request_id",
          "address_validation",
          "created_at"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de cette requête ; indiquez-le au support. Aucune session n'est créée."
          },
          "address_validation": {
            "$ref": "#/components/schemas/AddressValidationResult"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TravelRuleWalletProofFailureReason": {
        "type": "string",
        "enum": [
          "",
          "SIGNATURE_INVALID",
          "SIGNATURE_UNSUPPORTED_SCHEME",
          "DEPOSIT_NOT_FOUND",
          "DEPOSIT_UNCONFIRMED",
          "DEPOSIT_LOOKUP_FAILED",
          "DEPOSIT_MISMATCH",
          "DEPOSIT_STALE",
          "TXID_REUSED",
          "CHAIN_UNSUPPORTED",
          "WINDOW_EXPIRED",
          "OWNERSHIP_CHANGED",
          "METHOD_SWITCHED",
          "REVIEW_REJECTED",
          "ABANDONED"
        ],
        "description": "Raison pour laquelle une preuve de propriété du portefeuille, ou sa dernière tentative, n'a pas atteint le statut VERIFIED. Vide lorsque rien n'a échoué. Une preuve PENDING peut en comporter une : la dernière tentative a échoué et l'utilisateur final peut réessayer. DEPOSIT_MISMATCH, DEPOSIT_STALE, TXID_REUSED et REVIEW_REJECTED clôturent la preuve comme REJECTED. SIGNATURE_INVALID : la signature ne correspond pas au portefeuille et au défi. SIGNATURE_UNSUPPORTED_SCHEME : le portefeuille a signé dans un format que Didit ne vérifie pas. DEPOSIT_NOT_FOUND, DEPOSIT_UNCONFIRMED, DEPOSIT_LOOKUP_FAILED : le dépôt test n'est pas lisible ou pas encore confirmé ; Didit continue de vérifier jusqu'à la fermeture de la fenêtre de test. DEPOSIT_MISMATCH : la transaction n'envoie pas le montant attendu depuis le portefeuille vers l'adresse de dépôt. DEPOSIT_STALE : la transaction est antérieure au défi. TXID_REUSED : la transaction a déjà servi à prouver un autre portefeuille. CHAIN_UNSUPPORTED : la méthode n'est pas disponible sur cette blockchain. WINDOW_EXPIRED : la fenêtre de test a expiré. OWNERSHIP_CHANGED : le détenteur du portefeuille a changé, ou le portefeuille a été supprimé de votre carnet d'adresses après la création de la session de widget. METHOD_SWITCHED : l'utilisateur final a choisi une autre méthode avant de terminer celle-ci. REVIEW_REJECTED : votre réviseur a rejeté la capture d'écran. ABANDONED : la session de widget a expiré avant que l'utilisateur final n'ait terminé."
      },
      "TravelRuleWidgetProofError": {
        "type": "object",
        "properties": {
          "detail": {
            "type": "string",
            "description": "Message lisible par l'humain en anglais."
          },
          "code": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleWalletProofFailureReason"
              }
            ],
            "description": "Raison lisible par machine, afin qu'un client puisse afficher son propre message traduit."
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "VERIFIED",
              "REJECTED",
              "EXPIRED"
            ],
            "description": "Présent lorsque la preuve est clôturée : REJECTED par le dépôt qui vient d'être soumis (400), ou REJECTED ou EXPIRED lorsqu'une pièce justificative est envoyée pour une preuve déjà clôturée (409)."
          },
          "proof_id": {
            "type": "string",
            "format": "uuid",
            "description": "Présent avec le statut : la preuve clôturée."
          },
          "method": {
            "type": "string",
            "enum": [
              "MESSAGE_SIGNING",
              "SATOSHI_TEST",
              "SCREENSHOT",
              "SELF_DECLARATION"
            ],
            "description": "Présent avec le statut : la méthode de la preuve clôturée."
          },
          "max_attempts": {
            "type": "integer",
            "description": "Présent avec le statut : preuves de portefeuille rejetées autorisées par cette session."
          },
          "attempts_used": {
            "type": "integer",
            "description": "Présent avec le statut : preuves rejetées jusqu'à présent."
          },
          "attempts_remaining": {
            "type": "integer",
            "description": "Présent avec le statut : lorsqu'il est à 0, démarrer une autre preuve renvoie 409 et vous générez une nouvelle session de widget."
          }
        }
      },
      "TravelRuleWidgetProofCreate": {
        "type": "object",
        "required": [
          "method"
        ],
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "MESSAGE_SIGNING",
              "SATOSHI_TEST",
              "SCREENSHOT",
              "SELF_DECLARATION"
            ],
            "description": "La méthode de preuve choisie par l'utilisateur final. Elle doit faire partie des allowed_methods du contexte."
          },
          "wallet_address": {
            "type": "string",
            "maxLength": 128,
            "description": "Prend par défaut le wallet_address de la session. Doit correspondre au portefeuille du transfert lorsque la session est liée à un transfert."
          },
          "chain": {
            "type": "string",
            "maxLength": 32,
            "description": "Prend par défaut la blockchain de la session."
          }
        }
      },
      "TravelRuleWidgetProofVerifyResult": {
        "type": "object",
        "properties": {
          "proof_id": {
            "type": "string",
            "format": "uuid"
          },
          "method": {
            "type": "string",
            "enum": [
              "MESSAGE_SIGNING",
              "SATOSHI_TEST",
              "SCREENSHOT",
              "SELF_DECLARATION"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "VERIFIED",
              "REJECTED",
              "EXPIRED"
            ]
          },
          "is_ownership_verified": {
            "type": "boolean",
            "description": "Présent lorsque la preuve est VERIFIED : l'entrée du carnet d'adresses a désormais sa propriété vérifiée."
          },
          "transfer_status": {
            "type": "string",
            "nullable": true,
            "description": "Présent lorsque la preuve est VERIFIED : le statut du transfert lié, null s'il n'y en a aucun."
          },
          "detail": {
            "type": "string",
            "description": "Présent tant que la preuve reste PENDING : une capture d'écran soumise en attente d'examen, ou un dépôt de test qui n'est pas encore confirmé."
          },
          "code": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleWalletProofFailureReason"
              }
            ],
            "description": "Présent sur un dépôt de test en attente : raison pour laquelle il n'est pas encore confirmé."
          }
        }
      },
      "TravelRuleWalletProofReview": {
        "type": "object",
        "properties": {
          "proof_id": {
            "type": "string",
            "format": "uuid"
          },
          "method": {
            "type": "string",
            "enum": [
              "SCREENSHOT"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "VERIFIED",
              "REJECTED",
              "EXPIRED"
            ]
          },
          "wallet_address": {
            "type": "string"
          },
          "chain": {
            "type": "string",
            "description": "Identifiant canonique de la blockchain, par ex. ETH, BTC, SOL, TRX."
          },
          "holder_name": {
            "type": "string"
          },
          "is_ownership_verified": {
            "type": "boolean",
            "description": "Indique si l'entrée du carnet d'adresses a fait l'objet d'une vérification de propriété, par cette preuve ou par une autre."
          },
          "transaction_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "La transaction associée au transfert Travel Rule pour lequel la session de widget a été créée. Null pour une session créée sans transaction_id."
          },
          "file_name": {
            "type": "string",
            "nullable": true
          },
          "content_type": {
            "type": "string",
            "nullable": true
          },
          "screenshot_url": {
            "type": "string",
            "nullable": true,
            "description": "Lien temporaire vers la capture d'écran téléchargée. Listez à nouveau la file d'attente pour obtenir un lien actualisé."
          },
          "attempts": {
            "type": "integer",
            "description": "Nombre de fichiers que l'utilisateur final a téléchargés pour ce justificatif."
          },
          "failure_reason": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TravelRuleWalletProofFailureReason"
              }
            ],
            "description": "REVIEW_REJECTED après un refus, OWNERSHIP_CHANGED lorsque le portefeuille a changé de titulaire ou a été supprimé avant une décision. Vide dans les autres cas."
          },
          "method_chosen_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles l'utilisateur final a choisi la méthode par capture d'écran."
          },
          "decided_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "decided_by": {
            "type": "string",
            "description": "Qui a clôturé la preuve : review:<user identifier> pour un réviseur de la console, review pour une décision prise par clé API, widget ou sweeper lorsque Didit l'a clôturée automatiquement. Vide tant que le statut est PENDING."
          },
          "review_note": {
            "type": "string",
            "description": "La note envoyée avec la décision. Vide s'il n'y en a aucune."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TravelRuleWalletProofDecision": {
        "type": "object",
        "required": [
          "decision"
        ],
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "approve",
              "reject"
            ]
          },
          "note": {
            "type": "string",
            "maxLength": 512,
            "description": "Optionnel. Conservé avec la preuve et renvoyé sous le nom review_note."
          }
        }
      },
      "DigitalIdWalletApiWalletDigitalCredentialsRequest": {
        "type": "object",
        "properties": {
          "protocol": {
            "type": "string",
            "description": "openid4vp-v1-signed."
          },
          "request": {
            "type": "object",
            "additionalProperties": {},
            "description": "Transmettez tel quel : navigator.credentials.get({digital: request}) dans le navigateur, ou JSON.stringify(request) comme requestJson de GetDigitalCredentialOption sur Android. Signé par Didit pour votre application."
          }
        },
        "required": [
          "protocol",
          "request"
        ]
      },
      "DigitalIdWalletApiGoogleWalletWalletVerificationStartRequest": {
        "type": "object",
        "description": "Démarrer une vérification Google Wallet (USA, GBR, BRA, SGP, TWN).",
        "properties": {
          "vendor_data": {
            "type": "string",
            "nullable": true,
            "description": "Votre propre référence pour cette vérification (par exemple, votre identifiant d'utilisateur). Renvoyée dans les résultats et les webhooks."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "nullable": true,
            "description": "Objet JSON optionnel stocké avec la vérification et retourné dans les résultats et les webhooks."
          },
          "sandbox_scenario": {
            "type": "string",
            "minLength": 1,
            "description": "Applications en sandbox uniquement : le résultat simulé - 'wallet_cancelled', 'wallet_timeout' ou 'wallet_provider_error' ; la vérification réussit pour tout autre scénario (ou en l'absence de scénario). Rejeté sur les applications en production. Le catalogue complet est disponible à GET /v1/sandbox/scenarios/."
          },
          "country": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DigitalIdWalletApiGoogleWalletWalletVerificationStartCountryEnum"
              }
            ],
            "description": "Pays ISO 3166-1 alpha-3 de l'identité Google Wallet.\n\n* `USA` - USA\n* `GBR` - GBR\n* `BRA` - BRA\n* `SGP` - SGP\n* `TWN` - TWN"
          },
          "origin": {
            "type": "string",
            "minLength": 1,
            "description": "Endroit où votre page ou application sollicitera le portefeuille : l'origine https de votre page (son hôte doit figurer dans les allowed_return_hosts de l'application ou être son domaine en marque blanche), par exemple https://app.example.com, ou android:apk-key-hash:<base64 SHA-256 du certificat de signature de votre application, sans remplissage>. Le portefeuille refuse la requête partout ailleurs.",
            "maxLength": 256
          }
        },
        "required": [
          "country",
          "origin"
        ]
      },
      "DigitalIdWalletApiGoogleWalletWalletVerificationStartCountryEnum": {
        "enum": [
          "USA",
          "GBR",
          "BRA",
          "SGP",
          "TWN"
        ],
        "type": "string",
        "description": "* `USA` - USA\n* `GBR` - GBR\n* `BRA` - BRA\n* `SGP` - SGP\n* `TWN` - TWN"
      },
      "DigitalIdWalletApiWalletDigitalCredentialResponseRequest": {
        "type": "object",
        "description": "Ce que le portefeuille a répondu à votre page ou application, pour une vérification ``request_digital_credential``.",
        "properties": {
          "response": {
            "type": "object",
            "additionalProperties": {},
            "description": "Exactement ce que le portefeuille a renvoyé : {protocol, data} du DigitalCredential issu de navigator.credentials.get, ou le credentialJson analysé du DigitalCredential d'Android. Chiffré pour Didit ; ne le modifiez pas."
          }
        },
        "required": [
          "response"
        ]
      },
      "SessionFilesExport": {
        "type": "object",
        "description": "Un fichier ZIP contenant chaque fichier d'une session, dans sa qualité d'origine.",
        "required": [
          "export_id",
          "session_id",
          "status",
          "file_count",
          "size_bytes",
          "download_url",
          "expires_at",
          "error",
          "created_at",
          "completed_at"
        ],
        "properties": {
          "export_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant de l'export. Transmettez-le à `GET /v3/session/{sessionId}/files-export/{exportId}/`."
          },
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "La session dont proviennent les fichiers."
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "READY",
              "FAILED",
              "EXPIRED"
            ],
            "description": "`PENDING` et `PROCESSING` pendant la préparation du ZIP, `READY` dès qu'il peut être téléchargé, `FAILED` lorsqu'il n'a pas pu être préparé (demandez un nouvel export), `EXPIRED` une fois le ZIP supprimé."
          },
          "file_count": {
            "type": "integer",
            "nullable": true,
            "description": "Fichiers dans le ZIP. Défini uniquement tant que `status` est `READY`."
          },
          "size_bytes": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Taille du ZIP en octets. Renseignée uniquement lorsque `status` est `READY`."
          },
          "download_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL signée du ZIP, valide pendant une courte durée. Renseignée uniquement lorsque `status` est `READY` ; relisez l'export pour en obtenir une nouvelle."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure de suppression du fichier ZIP, 24 heures après qu'il a été prêt. Défini uniquement lorsque `status` est `READY`."
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Raison pour laquelle l'export a échoué, lorsque `status` est `FAILED`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date et heure de demande de l'export."
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date et heure auxquelles le fichier ZIP était prêt ou auxquelles l'export a échoué."
          }
        }
      },
      "TransactionRuleSuggestionsCreatedEvent": {
        "description": "Une exécution de suggestions de règles de transaction a proposé de nouvelles modifications de règles pour votre application. Envoyé lorsque les notifications par webhook sont activées dans les paramètres de suggestion de règles. Il n'y a pas de `status` de premier niveau.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "webhook_type": {
                "type": "string",
                "enum": [
                  "transaction_rule_suggestions.created"
                ],
                "description": "Toujours `transaction_rule_suggestions.created`."
              },
              "run_id": {
                "type": "string",
                "format": "uuid",
                "description": "L'exécution de suggestions qui a produit les nouvelles suggestions."
              },
              "open_count": {
                "type": "integer",
                "description": "Nombre de suggestions encore ouvertes après cette exécution, nouvelles suggestions incluses."
              },
              "suggestions": {
                "type": "array",
                "description": "Les suggestions créées par cette exécution.",
                "items": {
                  "type": "object",
                  "required": [
                    "suggestion_id",
                    "kind",
                    "title",
                    "rule_id",
                    "expected_impact"
                  ],
                  "properties": {
                    "suggestion_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "ADD",
                        "TWEAK",
                        "DISABLE"
                      ],
                      "description": "`ADD` propose une nouvelle règle, `TWEAK` modifie une règle existante, `DISABLE` en désactive une."
                    },
                    "title": {
                      "type": "string"
                    },
                    "rule_id": {
                      "type": "string",
                      "format": "uuid",
                      "nullable": true,
                      "description": "La règle à laquelle s'applique une suggestion `TWEAK` ou `DISABLE` ; `null` pour `ADD`."
                    },
                    "expected_impact": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "Ce que la modification ferait, tel que la suggestion l'affiche dans la Console."
                    }
                  }
                }
              }
            },
            "required": [
              "webhook_type",
              "run_id",
              "open_count",
              "suggestions"
            ]
          }
        ]
      },
      "GeolocationCheck": {
        "type": "object",
        "description": "Un résultat de vérification de localisation, la tentative acceptée d'un nœud de workflow. La mesure, l'incertitude et l'authenticité sont des clés distinctes, de sorte qu'une localisation précise non attestée se lit différemment d'une localisation imprécise attestée.",
        "properties": {
          "node_id": {
            "type": "string",
            "nullable": true,
            "description": "Nœud de workflow ayant produit ce résultat, afin qu'un workflow comportant deux étapes de vérification de localisation reste lisible."
          },
          "status": {
            "type": "string",
            "enum": [
              "Not Finished",
              "Approved",
              "Declined",
              "In Review",
              "Resub Requested"
            ],
            "description": "Statut au niveau de la fonctionnalité de cette étape de vérification de localisation, déterminé à partir de ses avertissements. Indépendant du `status` de la session."
          },
          "outcome": {
            "type": "string",
            "nullable": true,
            "description": "Ce qui s'est passé lors de cette tentative.",
            "enum": [
              "verified",
              "low_accuracy",
              "accuracy_undetermined",
              "stale",
              "approximate",
              "denied",
              "restricted",
              "unavailable",
              "timeout",
              "mock_detected",
              "outside_geofence",
              "in_blocked_area",
              "anonymizer_detected",
              "skipped",
              "replay_rejected",
              "unsupported_client",
              null
            ]
          },
          "permission": {
            "type": "string",
            "nullable": true,
            "description": "Ce que le système d'exploitation ou le navigateur a accordé. `not_requested` signifie que l'étape utilise uniquement la localisation IP de la connexion, de sorte qu'aucune autorisation n'est jamais demandée à la personne.",
            "enum": [
              "granted_precise",
              "granted_approximate",
              "denied",
              "restricted",
              "unavailable",
              "timeout",
              "dismissed",
              "not_requested",
              null
            ]
          },
          "latitude": {
            "type": "number",
            "nullable": true,
            "description": "Latitude WGS84 de la position. `null` lorsqu'il n'y a aucune position.",
            "format": "double"
          },
          "longitude": {
            "type": "number",
            "nullable": true,
            "description": "Longitude WGS84 de la position. `null` lorsqu'il n'y a aucune position.",
            "format": "double"
          },
          "accuracy_m": {
            "type": "number",
            "nullable": true,
            "description": "Rayon d'incertitude en mètres, au niveau de confiance indiqué dans `accuracy_confidence`.",
            "format": "double"
          },
          "accuracy_confidence": {
            "type": "string",
            "nullable": true,
            "description": "Niveau de confiance que la plateforme associe à `accuracy_m` : `p95` (navigateurs), `p68` (Android) ou `unspecified` (iOS).",
            "enum": [
              "p95",
              "p68",
              "unspecified",
              null
            ]
          },
          "measured_at": {
            "type": "string",
            "nullable": true,
            "description": "Date et heure auxquelles l'appareil a obtenu la position, selon sa propre horloge.",
            "format": "date-time"
          },
          "age_seconds": {
            "type": "integer",
            "nullable": true,
            "description": "Secondes écoulées entre la prise du relevé par l'appareil et sa réception par Didit."
          },
          "source": {
            "type": "string",
            "nullable": true,
            "description": "Provenance de la géolocalisation, lorsque la plateforme l'indique. `ip` signifie que la position correspond à la localisation IP de la connexion.",
            "enum": [
              "gps",
              "fused",
              "network",
              "wifi",
              "cell",
              "browser",
              "unknown",
              "ip",
              null
            ]
          },
          "platform": {
            "type": "string",
            "nullable": true,
            "description": "Le client ayant produit la correction.",
            "enum": [
              "web",
              "ios",
              "android",
              "react_native",
              "flutter",
              null
            ]
          },
          "sdk_version": {
            "type": "string",
            "nullable": true,
            "description": "Version du SDK qui a produit le correctif."
          },
          "is_mock": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque l'appareil indique que la position provient d'un fournisseur de localisation fictive ou d'un logiciel de simulation. `null` lorsque la plateforme ne le signale pas (les navigateurs ne peuvent pas le déterminer) ; `null` n'est pas `false`."
          },
          "produced_by_accessory": {
            "type": "boolean",
            "nullable": true,
            "description": "iOS uniquement : `true` lorsque la position a été obtenue à partir d'un accessoire externe. `null` ailleurs."
          },
          "integrity": {
            "type": "string",
            "enum": [
              "attested",
              "not_attested",
              "failed",
              "unsupported",
              "not_determined"
            ],
            "description": "Indique si une attestation d'appareil soutient le correctif. `unsupported` est ce que signalent les navigateurs, car le Web ne dispose d'aucun mécanisme d'attestation ; il ne s'agit pas d'un échec."
          },
          "country_code": {
            "type": "string",
            "nullable": true,
            "description": "Pays ISO 3166-1 alpha-2 dans lequel se trouve la localisation."
          },
          "region_code": {
            "type": "string",
            "nullable": true,
            "description": "Subdivision ISO 3166-2 dans laquelle se trouve la position."
          },
          "city": {
            "type": "string",
            "nullable": true,
            "description": "Lieu habité le plus proche, un libellé pour les réviseurs."
          },
          "geofence": {
            "type": "object",
            "description": "Résultat des règles de pays et de zone de l'étape.",
            "properties": {
              "enabled": {
                "type": "boolean",
                "description": "Indique si l'étape applique une règle relative au pays ou à la zone géographique."
              },
              "result": {
                "type": "string",
                "nullable": true,
                "description": "Situation de la position par rapport aux règles. `undetermined` signifie que le cercle de précision chevauche la frontière ou que la position ne correspond à aucun pays ; cela ne constitue pas une preuve de présence à l'extérieur.",
                "enum": [
                  "inside",
                  "outside",
                  "undetermined",
                  null
                ]
              }
            }
          },
          "inside_geofence": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque `geofence.result` est `inside`, `false` lorsqu'il est `outside`, `null` sinon."
          },
          "geofence_basis": {
            "type": "string",
            "nullable": true,
            "description": "À partir de quelle position le résultat de zone a été évalué : le point de positionnement `device`, ou la localisation `ip` de la connexion.",
            "enum": [
              "device",
              "ip",
              null
            ]
          },
          "inside_areas": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Identifiants des zones autorisées configurées dans lesquelles se trouve la position."
          },
          "blocked_areas": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Identifiants des zones bloquées configurées dans lesquelles se trouve la position."
          },
          "position_source": {
            "type": "string",
            "nullable": true,
            "description": "Provenance de la position pour l'étape, telle que configurée : l'appareil comparé à la localisation de l'IP, l'appareil uniquement ou la localisation de l'IP uniquement.",
            "enum": [
              "device_and_ip",
              "device_only",
              "ip_only",
              null
            ]
          },
          "anonymizers": {
            "type": "object",
            "nullable": true,
            "description": "L'état de la connexion et de l'appareil, chacun valant `true`, `false` ou `null` lorsque la source ne peut pas le déterminer.",
            "properties": {
              "vpn": {
                "type": "boolean",
                "nullable": true
              },
              "proxy": {
                "type": "boolean",
                "nullable": true
              },
              "tor": {
                "type": "boolean",
                "nullable": true
              },
              "spoofing": {
                "type": "boolean",
                "nullable": true
              },
              "emulator": {
                "type": "boolean",
                "nullable": true
              }
            }
          },
          "ip_distance_km": {
            "type": "number",
            "nullable": true,
            "description": "Distance jusqu'à la localisation IP de la session après soustraction des deux rayons d'incertitude ; `0` lorsqu'ils se chevauchent.",
            "format": "double"
          },
          "ip_distance_uncertainty_km": {
            "type": "number",
            "nullable": true,
            "description": "Rayon combiné qui a été soustrait : le rayon de localisation de l'IP plus la précision de cette position.",
            "format": "double"
          },
          "ip_consistent": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si `ip_distance_km` est inférieure ou égale à la distance configurée pour l'étape. `null` lorsque l'un des côtés est inconnu."
          },
          "document_distance_km": {
            "type": "number",
            "nullable": true,
            "description": "Distance jusqu'à l'adresse géocodée sur le document d'identité ou le justificatif de domicile. `null` lorsqu'aucune adresse n'est enregistrée.",
            "format": "double"
          },
          "travel_excused": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si la tolérance de déplacement de l'étape a excusé l'écart par rapport à l'adresse. Vaut `null` lorsque la tolérance est désactivée."
          },
          "consecutive_mismatches": {
            "type": "integer",
            "nullable": true,
            "description": "Lors de la dernière tentative : cette vérification ainsi que les non-concordances antérieures consécutives de la même personne."
          },
          "attempts": {
            "type": "integer",
            "description": "Numéro de cette tentative au sein du nœud, commençant à 1."
          },
          "consent": {
            "type": "object",
            "nullable": true,
            "description": "Le consentement donné par la personne avant l'invite système, enregistré avec la version du texte et la langue qu'elle a vues.",
            "properties": {
              "accepted_at": {
                "type": "string",
                "format": "date-time"
              },
              "version": {
                "type": "string",
                "nullable": true
              },
              "locale": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "feature": {
                  "type": "string",
                  "enum": [
                    "ID_VERIFICATION",
                    "NFC",
                    "LIVENESS",
                    "FACEMATCH",
                    "PROOF_OF_ADDRESS",
                    "PHONE",
                    "EMAIL",
                    "AML",
                    "LOCATION",
                    "DATABASE_VALIDATION",
                    "QUESTIONNAIRE",
                    "DOCUMENT_AI",
                    "KYB_REGISTRY",
                    "KYB_DOCUMENTS",
                    "KYB_KEY_PEOPLE",
                    "GEOLOCATION",
                    "SIGNATURE"
                  ],
                  "description": "La fonctionnalité qui a généré cet avertissement. La valeur identifie le bloc de fonctionnalités auquel appartient l'avertissement. Le tableau d'avertissements de chaque module utilise généralement la valeur correspondant à son module (par ex. `PHONE` dans `phone_verifications[].warnings`), mais l'énumération ci-dessus fait foi pour tous les avertissements de fonctionnalités sur le payload de décision."
                },
                "risk": {
                  "type": "string"
                },
                "additional_data": {
                  "type": "object",
                  "nullable": true
                },
                "log_type": {
                  "type": "string"
                },
                "short_description": {
                  "type": "string"
                },
                "long_description": {
                  "type": "string"
                },
                "node_id": {
                  "type": "string",
                  "description": "L'identifiant du nœud du graphe de workflow ayant généré cet avertissement"
                }
              }
            },
            "description": "Avertissements générés par cette étape de vérification de l'emplacement, avec `feature` défini sur `GEOLOCATION`. Les codes d'avertissement commencent par `LOCATION_`."
          }
        }
      },
      "GeolocationAttempt": {
        "type": "object",
        "description": "Une tentative d'étape de vérification de localisation : les mêmes clés que `geolocation_checks[]` à l'exception de `warnings`, plus l'horodatage de réception par Didit.",
        "properties": {
          "node_id": {
            "type": "string",
            "nullable": true,
            "description": "Nœud de workflow ayant produit ce résultat, afin qu'un workflow comportant deux étapes de vérification de localisation reste lisible."
          },
          "status": {
            "type": "string",
            "enum": [
              "Not Finished",
              "Approved",
              "Declined",
              "In Review",
              "Resub Requested"
            ],
            "description": "Statut au niveau de la fonctionnalité de cette étape de vérification de localisation, déterminé à partir de ses avertissements. Indépendant du `status` de la session."
          },
          "outcome": {
            "type": "string",
            "nullable": true,
            "description": "Ce qui s'est passé lors de cette tentative.",
            "enum": [
              "verified",
              "low_accuracy",
              "accuracy_undetermined",
              "stale",
              "approximate",
              "denied",
              "restricted",
              "unavailable",
              "timeout",
              "mock_detected",
              "outside_geofence",
              "in_blocked_area",
              "anonymizer_detected",
              "skipped",
              "replay_rejected",
              "unsupported_client",
              null
            ]
          },
          "permission": {
            "type": "string",
            "nullable": true,
            "description": "Ce que le système d'exploitation ou le navigateur a accordé. `not_requested` signifie que l'étape utilise uniquement la localisation IP de la connexion, de sorte qu'aucune autorisation n'est jamais demandée à la personne.",
            "enum": [
              "granted_precise",
              "granted_approximate",
              "denied",
              "restricted",
              "unavailable",
              "timeout",
              "dismissed",
              "not_requested",
              null
            ]
          },
          "latitude": {
            "type": "number",
            "nullable": true,
            "description": "Latitude WGS84 de la position. `null` lorsqu'il n'y a aucune position.",
            "format": "double"
          },
          "longitude": {
            "type": "number",
            "nullable": true,
            "description": "Longitude WGS84 de la position. `null` lorsqu'il n'y a aucune position.",
            "format": "double"
          },
          "accuracy_m": {
            "type": "number",
            "nullable": true,
            "description": "Rayon d'incertitude en mètres, au niveau de confiance indiqué dans `accuracy_confidence`.",
            "format": "double"
          },
          "accuracy_confidence": {
            "type": "string",
            "nullable": true,
            "description": "Niveau de confiance que la plateforme associe à `accuracy_m` : `p95` (navigateurs), `p68` (Android) ou `unspecified` (iOS).",
            "enum": [
              "p95",
              "p68",
              "unspecified",
              null
            ]
          },
          "measured_at": {
            "type": "string",
            "nullable": true,
            "description": "Date et heure auxquelles l'appareil a obtenu la position, selon sa propre horloge.",
            "format": "date-time"
          },
          "age_seconds": {
            "type": "integer",
            "nullable": true,
            "description": "Secondes écoulées entre la prise du relevé par l'appareil et sa réception par Didit."
          },
          "source": {
            "type": "string",
            "nullable": true,
            "description": "Provenance de la géolocalisation, lorsque la plateforme l'indique. `ip` signifie que la position correspond à la localisation IP de la connexion.",
            "enum": [
              "gps",
              "fused",
              "network",
              "wifi",
              "cell",
              "browser",
              "unknown",
              "ip",
              null
            ]
          },
          "platform": {
            "type": "string",
            "nullable": true,
            "description": "Le client ayant produit la correction.",
            "enum": [
              "web",
              "ios",
              "android",
              "react_native",
              "flutter",
              null
            ]
          },
          "sdk_version": {
            "type": "string",
            "nullable": true,
            "description": "Version du SDK qui a produit le correctif."
          },
          "is_mock": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque l'appareil indique que la position provient d'un fournisseur de localisation fictive ou d'un logiciel de simulation. `null` lorsque la plateforme ne le signale pas (les navigateurs ne peuvent pas le déterminer) ; `null` n'est pas `false`."
          },
          "produced_by_accessory": {
            "type": "boolean",
            "nullable": true,
            "description": "iOS uniquement : `true` lorsque la position a été obtenue à partir d'un accessoire externe. `null` ailleurs."
          },
          "integrity": {
            "type": "string",
            "enum": [
              "attested",
              "not_attested",
              "failed",
              "unsupported",
              "not_determined"
            ],
            "description": "Indique si une attestation d'appareil soutient le correctif. `unsupported` est ce que signalent les navigateurs, car le Web ne dispose d'aucun mécanisme d'attestation ; il ne s'agit pas d'un échec."
          },
          "country_code": {
            "type": "string",
            "nullable": true,
            "description": "Pays ISO 3166-1 alpha-2 dans lequel se trouve la localisation."
          },
          "region_code": {
            "type": "string",
            "nullable": true,
            "description": "Subdivision ISO 3166-2 dans laquelle se trouve la position."
          },
          "city": {
            "type": "string",
            "nullable": true,
            "description": "Lieu habité le plus proche, un libellé pour les réviseurs."
          },
          "geofence": {
            "type": "object",
            "description": "Résultat des règles de pays et de zone de l'étape.",
            "properties": {
              "enabled": {
                "type": "boolean",
                "description": "Indique si l'étape applique une règle relative au pays ou à la zone géographique."
              },
              "result": {
                "type": "string",
                "nullable": true,
                "description": "Situation de la position par rapport aux règles. `undetermined` signifie que le cercle de précision chevauche la frontière ou que la position ne correspond à aucun pays ; cela ne constitue pas une preuve de présence à l'extérieur.",
                "enum": [
                  "inside",
                  "outside",
                  "undetermined",
                  null
                ]
              }
            }
          },
          "inside_geofence": {
            "type": "boolean",
            "nullable": true,
            "description": "`true` lorsque `geofence.result` est `inside`, `false` lorsqu'il est `outside`, `null` sinon."
          },
          "geofence_basis": {
            "type": "string",
            "nullable": true,
            "description": "À partir de quelle position le résultat de zone a été évalué : le point de positionnement `device`, ou la localisation `ip` de la connexion.",
            "enum": [
              "device",
              "ip",
              null
            ]
          },
          "inside_areas": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Identifiants des zones autorisées configurées dans lesquelles se trouve la position."
          },
          "blocked_areas": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Identifiants des zones bloquées configurées dans lesquelles se trouve la position."
          },
          "position_source": {
            "type": "string",
            "nullable": true,
            "description": "Provenance de la position pour l'étape, telle que configurée : l'appareil comparé à la localisation de l'IP, l'appareil uniquement ou la localisation de l'IP uniquement.",
            "enum": [
              "device_and_ip",
              "device_only",
              "ip_only",
              null
            ]
          },
          "anonymizers": {
            "type": "object",
            "nullable": true,
            "description": "L'état de la connexion et de l'appareil, chacun valant `true`, `false` ou `null` lorsque la source ne peut pas le déterminer.",
            "properties": {
              "vpn": {
                "type": "boolean",
                "nullable": true
              },
              "proxy": {
                "type": "boolean",
                "nullable": true
              },
              "tor": {
                "type": "boolean",
                "nullable": true
              },
              "spoofing": {
                "type": "boolean",
                "nullable": true
              },
              "emulator": {
                "type": "boolean",
                "nullable": true
              }
            }
          },
          "ip_distance_km": {
            "type": "number",
            "nullable": true,
            "description": "Distance jusqu'à la localisation IP de la session après soustraction des deux rayons d'incertitude ; `0` lorsqu'ils se chevauchent.",
            "format": "double"
          },
          "ip_distance_uncertainty_km": {
            "type": "number",
            "nullable": true,
            "description": "Rayon combiné qui a été soustrait : le rayon de localisation de l'IP plus la précision de cette position.",
            "format": "double"
          },
          "ip_consistent": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si `ip_distance_km` est inférieure ou égale à la distance configurée pour l'étape. `null` lorsque l'un des côtés est inconnu."
          },
          "document_distance_km": {
            "type": "number",
            "nullable": true,
            "description": "Distance jusqu'à l'adresse géocodée sur le document d'identité ou le justificatif de domicile. `null` lorsqu'aucune adresse n'est enregistrée.",
            "format": "double"
          },
          "travel_excused": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si la tolérance de déplacement de l'étape a excusé l'écart par rapport à l'adresse. Vaut `null` lorsque la tolérance est désactivée."
          },
          "consecutive_mismatches": {
            "type": "integer",
            "nullable": true,
            "description": "Lors de la dernière tentative : cette vérification ainsi que les non-concordances antérieures consécutives de la même personne."
          },
          "attempts": {
            "type": "integer",
            "description": "Numéro de cette tentative au sein du nœud, commençant à 1."
          },
          "consent": {
            "type": "object",
            "nullable": true,
            "description": "Le consentement donné par la personne avant l'invite système, enregistré avec la version du texte et la langue qu'elle a vues.",
            "properties": {
              "accepted_at": {
                "type": "string",
                "format": "date-time"
              },
              "version": {
                "type": "string",
                "nullable": true
              },
              "locale": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "received_at": {
            "type": "string",
            "nullable": true,
            "description": "Date et heure auxquelles Didit a reçu la tentative.",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BiometricRetention": {
        "type": "object",
        "description": "Moment où les données biométriques en direct de cette session sont supprimées.",
        "required": [
          "jurisdictions",
          "deletes_at"
        ],
        "properties": {
          "jurisdictions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Codes des États américains dont les règles biométriques fixent une limite de suppression pour cette personne (`US` lorsque l'État est inconnu). Vide si aucune ne s'applique."
          },
          "deletes_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "La date à laquelle les données biométriques en direct (images de visage et gabarits) de cette session sont supprimées, d'après le paramètre de conservation de votre application et, le cas échéant, la limite légale pour la juridiction de la personne. `null` lorsqu'aucune date ne s'applique pour le moment."
          }
        }
      },
      "TravelRuleManualMatchRequest": {
        "type": "object",
        "required": [
          "transaction_id"
        ],
        "properties": {
          "transaction_id": {
            "type": "string",
            "format": "uuid",
            "description": "Le `transaction_id` du message Travel Rule reçu (une ligne avec `kind: message`)."
          }
        }
      },
      "TravelRuleManualMatchResponse": {
        "type": "object",
        "required": [
          "deposit",
          "message"
        ],
        "properties": {
          "deposit": {
            "$ref": "#/components/schemas/TravelRuleTransferRow"
          },
          "message": {
            "$ref": "#/components/schemas/TravelRuleTransferRow"
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "La clé API de votre application, issue de Développeurs -> Clés API dans la Business Console. La clé principale dispose d'un accès complet. Une clé nommée peut être restreinte : aucun, lecture ou écriture par ressource, limitée à certains workflows ou aux sessions approuvées, à une liste d'adresses IP et à une date d'expiration. 401 signifie que la clé est incorrecte, révoquée ou expirée ; 403 signifie qu'aucune clé n'a été envoyée, que la clé n'a pas accès à cette ressource ou action, ou que la requête provient d'une adresse hors de sa liste d'IP ; 404 sur une route de session signifie que la session est hors des workflows ou des statuts de la clé. Une clé sans accès aux médias reçoit les URL d'images, de vidéos et de PDF à null, et une clé sans accès en écriture aux sessions reçoit les liens et tokens de session à null. Voir https://docs.didit.me/console/api-keys."
      },
      "TransactionTokenAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Transaction-Token",
        "description": "Token restreint de courte durée généré par votre backend via POST /v3/transactions/sdk-token/. Utilisé par les SDK Didit sur les endpoints /v1/transactions/ côté appareil."
      },
      "SessionTokenAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Session-Token",
        "description": "Token de courte durée renvoyé dans le champ `session_token` de POST /v3/session/. Utilisé par le flux de vérification hébergé (et les interfaces de sandbox personnalisées) pour appeler des endpoints limités à la session pour le compte de l'utilisateur en cours de vérification, sans votre clé API côté serveur."
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Le token d'accès client-credentials de l'application."
      },
      "CaseRequestToken": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Case-Request-Token",
        "description": "Identifiant spécifique à la requête issu du lien sécurisé. Accorde l'accès uniquement à cette requête."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Non autorisé",
        "content": {
          "application/json": {
            "examples": {
              "Invalid API Key": {
                "summary": "Clé API non valide",
                "value": {
                  "detail": "Invalid API Key."
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Interdit",
        "content": {
          "application/json": {
            "examples": {
              "No Permission": {
                "summary": "Aucune autorisation",
                "value": {
                  "detail": "You do not have permission to perform this action."
                }
              },
              "Not Enough Credits": {
                "summary": "Crédits insuffisants",
                "value": {
                  "error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Introuvable",
        "content": {
          "application/json": {
            "examples": {
              "Not Found": {
                "summary": "Introuvable",
                "value": {
                  "detail": "Resource not found."
                }
              }
            }
          }
        }
      },
      "PhoneRiskValidationError": {
        "description": "Échec de la validation de la requête.",
        "content": {
          "application/json": {
            "examples": {
              "Missing phone number": {
                "summary": "Numéro de téléphone manquant",
                "value": {
                  "phone_number": [
                    "This field is required."
                  ]
                }
              },
              "Invalid phone number": {
                "summary": "Numéro de téléphone non valide",
                "value": {
                  "phone_number": [
                    "Invalid phone number provided."
                  ]
                }
              },
              "Invalid signal IP": {
                "summary": "IP de signal non valide",
                "value": {
                  "signals": {
                    "ip": [
                      "Enter a valid IPv4 or IPv6 address."
                    ]
                  }
                }
              }
            }
          }
        }
      },
      "EmailRiskValidationError": {
        "description": "Échec de la validation de la requête.",
        "content": {
          "application/json": {
            "examples": {
              "Missing email": {
                "summary": "E-mail manquant",
                "value": {
                  "email": [
                    "This field is required."
                  ]
                }
              },
              "Invalid email": {
                "summary": "E-mail non valide",
                "value": {
                  "email": [
                    "Enter a valid email address."
                  ]
                }
              },
              "Invalid country hint": {
                "summary": "Indication de pays non valide",
                "value": {
                  "country_code": [
                    "Ensure this field has no more than 3 characters."
                  ]
                }
              }
            }
          }
        }
      },
      "IPRiskValidationError": {
        "description": "Échec de la validation de la requête.",
        "content": {
          "application/json": {
            "examples": {
              "Missing IP address": {
                "summary": "Adresse IP manquante",
                "value": {
                  "ip_address": [
                    "This field is required."
                  ]
                }
              },
              "Invalid IP address": {
                "summary": "Adresse IP non valide",
                "value": {
                  "ip_address": [
                    "Enter a valid IPv4 or IPv6 address."
                  ]
                }
              },
              "Country hint too long": {
                "summary": "Indication de pays trop longue",
                "value": {
                  "claimed_country": [
                    "Ensure this field has no more than 3 characters."
                  ]
                }
              }
            }
          }
        }
      },
      "RiskPermissionDenied": {
        "description": "La clé API est manquante ou invalide, ou l'organisation ne peut pas couvrir la recherche en direct. Cette API ne renvoie jamais `401`.",
        "content": {
          "application/json": {
            "examples": {
              "Missing or invalid API key": {
                "summary": "Aucun en-tête `x-api-key`, ou la clé est non valide ou révoquée",
                "value": {
                  "detail": "You do not have permission to perform this action."
                }
              },
              "Not enough credits": {
                "summary": "Le solde de l'organisation ne peut pas couvrir le prix de la recherche",
                "value": {
                  "error": "You don't have enough credits to perform this request."
                }
              }
            }
          }
        }
      },
      "RateLimitedWrite": {
        "description": "La limite d'écriture partagée de 300 requêtes par minute et par clé API a été dépassée. Respectez l'en-tête `Retry-After` avant de réessayer.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "detail"
              ],
              "properties": {
                "detail": {
                  "type": "string"
                }
              }
            },
            "example": {
              "detail": "Write request rate limit exceeded. You can make up to 300 requests per minute."
            }
          }
        }
      },
      "AddressValidationValidationError": {
        "description": "Le corps de la requête n'est pas valide : un `country` manquant ou inconnu, aucune adresse, ou à la fois `address` et les champs structurés.",
        "content": {
          "application/json": {
            "examples": {
              "Unknown country": {
                "value": {
                  "country": [
                    "Use an ISO 3166-1 alpha-2 or alpha-3 country code, e.g. 'US' or 'USA'."
                  ]
                }
              },
              "No address": {
                "value": {
                  "address": [
                    "Send the address: 'address' on one line, or the structured fields with 'address_line_1'."
                  ]
                }
              },
              "Both shapes": {
                "value": {
                  "address": [
                    "Send either 'address' or the structured fields (address_line_1, ...), not both."
                  ]
                }
              }
            }
          }
        }
      },
      "AddressValidationPermissionDenied": {
        "description": "La clé API est manquante ou invalide, une clé restreinte ne dispose pas de l'accès en écriture à `sessions`, ou l'organisation ne peut pas couvrir la validation. Cette API ne renvoie jamais `401`.",
        "content": {
          "application/json": {
            "examples": {
              "Missing or invalid API key": {
                "value": {
                  "detail": "You do not have permission to perform this action."
                }
              },
              "Not enough credits": {
                "value": {
                  "detail": "You don't have enough credits to perform this request. Please top up at https://business.didit.me",
                  "code": "insufficient_credits"
                }
              }
            }
          }
        }
      },
      "DocumentProcessingBusy": {
        "description": "Un nombre trop important de documents est actuellement en cours de traitement, cet envoi n'a donc pas été traité : rien n'a été stocké et aucune tentative n'a été utilisée. Renvoyez le même fichier après le nombre de secondes indiqué dans `Retry-After`. Effectuez le branchement en fonction de `code`, et non du texte du message.",
        "headers": {
          "Retry-After": {
            "description": "Nombre de secondes à attendre avant d'envoyer à nouveau la même requête.",
            "schema": {
              "type": "integer",
              "example": 10
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "detail",
                "code"
              ],
              "properties": {
                "detail": {
                  "type": "string"
                },
                "code": {
                  "type": "string",
                  "enum": [
                    "document_processing_busy"
                  ]
                }
              }
            },
            "example": {
              "detail": "We are busy processing documents. Please try again in a moment.",
              "code": "document_processing_busy"
            }
          }
        }
      }
    },
    "parameters": {
      "WebhookSignature": {
        "name": "X-Signature",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "HMAC-SHA256 hexadécimal en minuscules, calculé avec le secret de la destination, sur le corps brut exact de la requête."
      },
      "WebhookSignatureV2": {
        "name": "X-Signature-V2",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "HMAC-SHA256 hexadécimal en minuscules, calculé avec le secret de la destination, sur le JSON canonique du corps (clés triées, sans espaces, caractères non-ASCII non échappés). Recommandé, car il résiste aux middlewares qui réencodent le corps."
      },
      "WebhookSignatureSimple": {
        "name": "X-Signature-Simple",
        "in": "header",
        "required": true,
        "deprecated": true,
        "schema": {
          "type": "string"
        },
        "description": "HMAC-SHA256 hexadécimal en minuscules, calculé avec le secret de la destination, sur la base de `{timestamp}:{session_id}:{status}:{webhook_type}` (les champs manquants étant des chaînes vides). Couvre uniquement l'enveloppe, jamais le payload."
      },
      "WebhookTimestamp": {
        "name": "X-Timestamp",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Temps Unix en secondes, égal au `timestamp` du corps. Rejetez les livraisons datant de plus de quelques minutes."
      }
    }
  },
  "x-webhooks": {
    "status.updated": {
      "post": {
        "summary": "Statut de la session modifié",
        "description": "Une session de vérification a changé de statut. `decision` est envoyé uniquement pour `Approved`, `Declined`, `In Review` et `Abandoned` ; il a la structure de `GET /v3/session/{sessionId}/decision/` pour les destinations sur la version 3 des webhooks (par défaut), et l'ancienne structure réduite pour les destinations de version 1 ou 2. Les sessions d'entreprise reçoivent toujours la décision d'entreprise en version 3.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionStatusUpdatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "data.updated": {
      "post": {
        "summary": "Données de la session modifiées",
        "description": "Données d'une session de vérification modifiées sans changement de statut, par exemple après une modification lors d'un examen manuel, le forçage d'une étape ou un nouveau filtrage de surveillance continue. `decision` n'est envoyée que pour `Approved`, `Declined`, `In Review` et `Abandoned` ; elle a la structure de `GET /v3/session/{sessionId}/decision/` pour les destinations configurées sur la version 3 des webhooks (version par défaut), et l'ancienne structure réduite pour les destinations en version 1 ou 2. Les sessions d'entreprise reçoivent toujours la décision d'entreprise de version 3.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionDataUpdatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "user.status.updated": {
      "post": {
        "summary": "Statut de l'utilisateur modifié",
        "description": "Un utilisateur a changé de statut. Non envoyé lors de la création de l'utilisateur.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserStatusUpdatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "user.data.updated": {
      "post": {
        "summary": "Données utilisateur modifiées",
        "description": "Champs d'un utilisateur modifiés. Non envoyé lors de la création de l'utilisateur. Une seule sauvegarde peut générer à la fois un événement de statut et un événement de données.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserDataUpdatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "business.status.updated": {
      "post": {
        "summary": "Statut de l'entreprise modifié",
        "description": "Une entreprise a changé de statut. Non envoyé lorsque l'entreprise est créée.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BusinessStatusUpdatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "business.data.updated": {
      "post": {
        "summary": "Données de l'entreprise modifiées",
        "description": "Champs d'une entreprise modifiés. Non envoyé lors de la création de l'entreprise. Une seule sauvegarde peut générer à la fois un événement de statut et un événement de données.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BusinessDataUpdatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "transaction.created": {
      "post": {
        "summary": "Transaction créée",
        "description": "Une transaction a été créée et filtrée. Envoyé uniquement pour les applications de production.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionCreatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "transaction.status.updated": {
      "post": {
        "summary": "Statut de la transaction modifié",
        "description": "Une transaction a changé de statut, à la suite d'une règle, d'un examen ou d'une action de l'utilisateur final. Envoyé uniquement pour les applications de production.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionStatusUpdatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "travel_rule.status.updated": {
      "post": {
        "summary": "Statut Travel Rule modifié",
        "description": "Un échange Travel Rule a changé de statut. Envoyé à chaque transition jusqu'à `FINISHED`, `CANCELLED` ou `EXPIRED` inclus, jamais après. Envoyé pour les applications en production et, pour les échanges Travel Rule, également pour les applications sandbox (`environment: sandbox`). Il n'y a pas de `status` de premier niveau.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TravelRuleStatusUpdatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "workflow.compliance_changed": {
      "post": {
        "summary": "Conformité du workflow modifiée",
        "description": "Le statut de conformité d'un workflow publié a changé après une réévaluation. Un événement par workflow. Il n'y a pas de `status` au niveau supérieur.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowComplianceChangedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "kyb.registry_search.resolved": {
      "post": {
        "summary": "Recherche d'entreprise résolue (rappel non signé)",
        "description": "Corps du rappel envoyé à l'URL `webhook_url` de `POST /v3/kyb/search/` une fois la recherche dans le registre résolue. Il n'est pas signé : la requête contient `X-Didit-Unsigned-Callback: true` et aucun des en-têtes de signature, confirmez-le donc en faisant correspondre `request_id` avec une recherche que vous avez lancée. Utilise `event_type`, et non `webhook_type`.",
        "tags": [
          "Webhook"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KYBRegistrySearchResolvedCallback"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    },
    "transaction_rule_suggestions.created": {
      "post": {
        "summary": "Suggestions de règles de transaction créées",
        "description": "Une exécution de suggestions de règles de transaction a proposé de nouvelles modifications de règles pour votre application. Envoyé lorsque les notifications par webhook sont activées dans les paramètres de suggestion de règles. Il n'y a pas de `status` de premier niveau.",
        "tags": [
          "Webhook"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureV2"
          },
          {
            "$ref": "#/components/parameters/WebhookSignatureSimple"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionRuleSuggestionsCreatedEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Toute réponse 2xx accuse réception de la livraison. De nouvelles tentatives sont effectuées pour les autres réponses et en cas de délai d'attente dépassé ; voir https://docs.didit.me/integration/webhooks."
          }
        }
      }
    }
  }
}
