{
  "openapi": "3.1.0",
  "info": {
    "title": "Checkwise API",
    "version": "1.1.0",
    "summary": "Vérification d'informations avec verdicts sourcés et sources notées à l'avance.",
    "description": "L'API Checkwise vérifie une affirmation, un article, une image ou un domaine, et renvoie un verdict sourcé.\n\nLe modèle de langage ne décide pas du verdict. Il extrait les affirmations et lit les sources trouvées ;\nle verdict est ensuite calculé à partir des verdicts source par source, chaque source étant pondérée par\nune note de fiabilité établie avant la vérification, selon une méthodologie publique.\n\nMéthodologie de notation : https://checkwise.ai/rating-methodology\nBase publique des sites notés : https://checkwise.ai/sites\n\nHébergé en Europe.",
    "contact": {
      "name": "Checkwise",
      "url": "https://checkwise.ai/contact"
    },
    "termsOfService": "https://checkwise.ai/terms"
  },
  "servers": [
    {
      "url": "https://developer.checkwise.ai/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyHeader": []
    },
    {
      "BearerKey": []
    }
  ],
  "tags": [
    {
      "name": "Fact-check",
      "description": "Vérification d'une affirmation, d'un article ou d'une image"
    },
    {
      "name": "Notation de sites",
      "description": "Fiabilité d'un domaine, lettre de A à D"
    },
    {
      "name": "Images",
      "description": "Détection d'images générées par IA"
    }
  ],
  "paths": {
    "/check": {
      "post": {
        "tags": [
          "Fact-check"
        ],
        "summary": "Vérifier une affirmation, un article ou une image",
        "description": "Fournir exactement l'un des trois champs. Les affirmations vérifiables sont extraites, les sources recherchées, puis un verdict est calculé par affirmation et pour l'ensemble.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "Texte libre contenant une ou plusieurs affirmations"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Adresse d'un article à vérifier"
                  },
                  "image": {
                    "type": "string",
                    "description": "Image encodée en base64"
                  }
                },
                "anyOf": [
                  {
                    "required": [
                      "text"
                    ]
                  },
                  {
                    "required": [
                      "url"
                    ]
                  },
                  {
                    "required": [
                      "image"
                    ]
                  }
                ]
              },
              "examples": {
                "texte": {
                  "value": {
                    "text": "Le taux de chômage en France est passé sous les 7 % en 2025."
                  }
                },
                "article": {
                  "value": {
                    "url": "https://example.org/un-article"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vérification effectuée",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/NoCredits"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/rate-site": {
      "post": {
        "tags": [
          "Notation de sites"
        ],
        "summary": "Obtenir la note de fiabilité d'un domaine",
        "description": "Renvoie la lettre de fiabilité du domaine, de A à D, la même que sur checkwise.ai, avec son libellé. Un domaine inconnu déclenche une analyse complète, plus lente qu'un domaine déjà évalué. Le détail par critère n'est pas renvoyé.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": "string",
                    "description": "Nom de domaine, sans protocole ni chemin"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Adresse dont le domaine sera extrait"
                  }
                },
                "anyOf": [
                  {
                    "required": [
                      "domain"
                    ]
                  },
                  {
                    "required": [
                      "url"
                    ]
                  }
                ]
              },
              "examples": {
                "domaine": {
                  "value": {
                    "domain": "lemonde.fr"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Notation du domaine",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteRatingResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/NoCredits"
          },
          "404": {
            "description": "Domaine inconnu et non évaluable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/image-analysis": {
      "post": {
        "tags": [
          "Images"
        ],
        "summary": "Déterminer si une image a été générée par une IA",
        "description": "Renvoie un score de détection et une explication. Aucun détecteur n'étant fiable à 100 %, le résultat est un indice à croiser avec la provenance de l'image. Endpoint en accès anticipé : ouvert sur demande.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "image": {
                    "type": "string",
                    "description": "Image encodée en base64 (JPEG, PNG, WebP)"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Adresse de l'image, utilisée si `image` est absent"
                  }
                },
                "anyOf": [
                  {
                    "required": [
                      "image"
                    ]
                  },
                  {
                    "required": [
                      "url"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Analyse effectuée",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/NoCredits"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Checkwise-API-Key",
        "description": "Clé d'API."
      },
      "BearerKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Même clé, transmise en `Authorization: Bearer <clé>`."
      }
    },
    "schemas": {
      "RateLimit": {
        "type": "object",
        "description": "État des crédits. Une vérification consomme un crédit.",
        "properties": {
          "credits_total": {
            "type": "integer"
          },
          "credits_remaining": {
            "type": "integer"
          }
        }
      },
      "Source": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "organization": {
            "type": "string",
            "nullable": true
          },
          "summary": {
            "type": "string",
            "nullable": true,
            "description": "Ce que dit cette source à propos de l'affirmation"
          },
          "verdict": {
            "type": "string",
            "enum": [
              "true",
              "false",
              "mixed",
              "not_rated"
            ],
            "description": "Verdict de cette source prise isolément"
          },
          "site_rating": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D",
              "not_rated"
            ],
            "description": "Lettre de fiabilité du site, la même que sur checkwise.ai, ou not_rated s'il n'est pas encore évalué"
          },
          "biases": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Claim": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "c1"
            ]
          },
          "text": {
            "type": "string",
            "description": "L'affirmation telle qu'extraite"
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "verdict": {
            "type": "string",
            "enum": [
              "true",
              "false",
              "mixed",
              "not_rated"
            ],
            "description": "Verdict calculé à partir des verdicts par source, jamais décidé par un modèle de langage seul."
          },
          "confirmed": {
            "type": "boolean",
            "description": "Vrai si toutes les sources retenues confirment l'affirmation, sur au moins deux sources"
          },
          "verdict_level": {
            "type": "string",
            "enum": [
              "confirmed",
              "likely_true",
              "mixed",
              "refuted",
              "no_evidence"
            ],
            "description": "Niveau affiché sur checkwise.ai et dans l'extension, fonction du verdict et de confirmed"
          },
          "verdict_label": {
            "type": "string",
            "description": "Libellé du niveau, par exemple « Likely True »"
          },
          "biases": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources_kept": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Source"
            },
            "description": "Sources retenues, cliquables"
          }
        }
      },
      "CheckResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "report_code": {
            "type": "string",
            "description": "Identifiant du rapport, consultable publiquement s'il a été rendu public"
          },
          "global_verdict": {
            "type": "string",
            "enum": [
              "true",
              "false",
              "mixed",
              "not_rated"
            ],
            "description": "Verdict de l'affirmation unique, sinon le plus fréquent"
          },
          "global_confirmed": {
            "type": "boolean"
          },
          "global_verdict_level": {
            "type": "string",
            "enum": [
              "confirmed",
              "likely_true",
              "mixed",
              "refuted",
              "no_evidence"
            ]
          },
          "global_verdict_label": {
            "type": "string"
          },
          "synthesis": {
            "type": "string",
            "nullable": true
          },
          "claims": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Claim"
            }
          },
          "processing_time_ms": {
            "type": "integer"
          },
          "metadata": {
            "type": "object",
            "properties": {
              "total_sources": {
                "type": "integer"
              },
              "input_type": {
                "type": "string",
                "enum": [
                  "text",
                  "url",
                  "image"
                ]
              },
              "credits_consumed": {
                "type": "integer"
              }
            }
          },
          "rate_limit": {
            "$ref": "#/components/schemas/RateLimit"
          }
        }
      },
      "SiteRatingResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "domain": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "country_code": {
            "type": "string",
            "nullable": true
          },
          "region": {
            "type": "string",
            "nullable": true
          },
          "type": {
            "type": "string",
            "nullable": true
          },
          "language": {
            "type": "string",
            "nullable": true
          },
          "letter": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D"
            ],
            "nullable": true,
            "description": "Lettre de fiabilité, attribuée selon la méthodologie publique"
          },
          "verdict": {
            "type": "string",
            "nullable": true,
            "description": "Libellé de la lettre, par exemple « Excellent reliability »"
          },
          "last_updated": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "rate_limit": {
            "$ref": "#/components/schemas/RateLimit"
          }
        }
      },
      "ImageResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "verdict": {
            "type": "string",
            "enum": [
              "ai_generated",
              "likely_ai",
              "uncertain",
              "likely_real",
              "authentic"
            ],
            "description": "Conclusion de l'analyse"
          },
          "ai_score": {
            "type": "number",
            "description": "Score de détection, de 0 (authentique) à 100 (générée)"
          },
          "is_ai": {
            "type": "boolean"
          },
          "confidence": {
            "type": "number",
            "nullable": true,
            "description": "Confiance du détecteur dans sa conclusion"
          },
          "explanation": {
            "type": "string",
            "nullable": true
          },
          "generator": {
            "type": "string",
            "nullable": true,
            "description": "Générateur identifié, quand il l'est"
          },
          "heatmap": {
            "type": "string",
            "nullable": true,
            "description": "Carte des zones ayant pesé, encodée en base64"
          },
          "processing_time_ms": {
            "type": "integer"
          },
          "rate_limit": {
            "$ref": "#/components/schemas/RateLimit"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "examples": [
              false
            ]
          },
          "error": {
            "type": "string",
            "examples": [
              "UNAUTHORIZED"
            ]
          },
          "message": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Clé d'API absente ou invalide",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ValidationError": {
        "description": "Requête incomplète ou mal formée",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NoCredits": {
        "description": "Crédits épuisés pour cette clé",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InternalError": {
        "description": "Erreur interne",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}