{
  "openapi": "3.1.0",
  "info": {
    "title": "Djinn Doc Trust",
    "description": "Avis d'authenticité documentaire par règles (évaluation, jamais autorisation)",
    "version": "0.1.0"
  },
  "paths": {
    "/health": {
      "get": {
        "summary": "Health",
        "description": "Health check, sans authentification.",
        "operationId": "health_health_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/authenticity/analyze": {
      "post": {
        "summary": "Analyze",
        "description": "Avis d'authenticité d'un justificatif (PDF ou image) : évaluation, jamais autorisation.\n\nLe type réel du fichier est lu dans ses octets, pas dans son nom. `fields` est un objet JSON\nfacultatif (16 Kio max) des champs déjà extraits ; ses valeurs ne sont jamais journalisées.",
        "operationId": "analyze_v1_authenticity_analyze_post",
        "parameters": [
          {
            "name": "X-API-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_analyze_v1_authenticity_analyze_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyzeResponse"
                }
              }
            }
          },
          "413": {
            "description": "Fichier de plus de 50 Mio (`file_too_large`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "`empty_file`, `unsupported_type`, `unreadable_file` ou `invalid_fields`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AnalyzeResponse": {
        "properties": {
          "verdict": {
            "type": "string",
            "enum": [
              "consistent",
              "suspicious",
              "inconsistent"
            ],
            "title": "Verdict",
            "description": "`consistent` (aucun signal notable), `suspicious` (à vérifier), `inconsistent` (au moins deux signaux forts de familles différentes)."
          },
          "score": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Score",
            "description": "Indicateur de tri, pas une probabilité : min(1, 0,35 x signaux forts + 0,1 x signaux faibles). Plus il est haut, plus il y a à vérifier."
          },
          "signals": {
            "items": {
              "$ref": "#/components/schemas/SignalOut"
            },
            "type": "array",
            "title": "Signals"
          },
          "explanation": {
            "type": "string",
            "title": "Explanation"
          },
          "rules_version": {
            "type": "string",
            "title": "Rules Version"
          },
          "document_sha256": {
            "type": "string",
            "title": "Document Sha256"
          },
          "document_type": {
            "type": "string",
            "enum": [
              "rib",
              "receipt",
              "attestation",
              "resume",
              "id_card",
              "other"
            ],
            "title": "Document Type"
          },
          "analysed_at": {
            "type": "string",
            "format": "date-time",
            "title": "Analysed At"
          }
        },
        "type": "object",
        "required": [
          "verdict",
          "score",
          "signals",
          "explanation",
          "rules_version",
          "document_sha256",
          "document_type",
          "analysed_at"
        ],
        "title": "AnalyzeResponse",
        "description": "Avis d'authenticité : une évaluation, jamais une autorisation."
      },
      "Body_analyze_v1_authenticity_analyze_post": {
        "properties": {
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File"
          },
          "document_type": {
            "type": "string",
            "enum": [
              "rib",
              "receipt",
              "attestation",
              "resume",
              "id_card",
              "other"
            ],
            "title": "Document Type"
          },
          "fields": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Fields"
          }
        },
        "type": "object",
        "required": [
          "file",
          "document_type"
        ],
        "title": "Body_analyze_v1_authenticity_analyze_post"
      },
      "ErrorBody": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code",
            "description": "`empty_file`, `file_too_large`, `unsupported_type`, `unreadable_file` ou `invalid_fields`."
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "title": "ErrorBody"
      },
      "ErrorDetail": {
        "properties": {
          "detail": {
            "$ref": "#/components/schemas/ErrorBody"
          }
        },
        "type": "object",
        "required": [
          "detail"
        ],
        "title": "ErrorDetail"
      },
      "HealthResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status"
          },
          "service": {
            "type": "string",
            "title": "Service"
          },
          "version": {
            "type": "string",
            "title": "Version"
          },
          "rules_version": {
            "type": "string",
            "title": "Rules Version"
          },
          "tsl_sequence": {
            "type": "integer",
            "title": "Tsl Sequence"
          },
          "tsl_issued": {
            "type": "string",
            "title": "Tsl Issued",
            "description": "Date d'émission de la TSL embarquée (AAAA-MM-JJ)."
          }
        },
        "type": "object",
        "required": [
          "status",
          "service",
          "version",
          "rules_version",
          "tsl_sequence",
          "tsl_issued"
        ],
        "title": "HealthResponse",
        "description": "Response for the health check endpoint."
      },
      "SignalOut": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code"
          },
          "family": {
            "type": "string",
            "enum": [
              "metadata",
              "structure",
              "fonts",
              "image",
              "content",
              "2ddoc"
            ],
            "title": "Family"
          },
          "strength": {
            "type": "string",
            "enum": [
              "info",
              "weak",
              "strong"
            ],
            "title": "Strength"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Message en français, sans donnée métier."
          },
          "detail": {
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ]
            },
            "type": "object",
            "title": "Detail",
            "description": "Métadonnées techniques seulement (producteur, nombre de révisions...). Jamais une valeur métier (IBAN, montant, nom)."
          }
        },
        "type": "object",
        "required": [
          "code",
          "family",
          "strength",
          "message"
        ],
        "title": "SignalOut"
      }
    }
  }
}
