{
  "openapi": "3.1.0",
  "info": {
    "title": "doesmybrandexist.io — scan de visibilité IA",
    "version": "1.0.0",
    "description": "Les deux routes de l API du scan. Elle est FERMEE : une cle est exigee. Les scores sont declares par les modeles d IA eux-memes, en une passe, a l instant du scan.",
    "contact": {
      "name": "Greeneris",
      "email": "hello@greeneris.io",
      "url": "https://geo.greeneris.io"
    }
  },
  "servers": [
    {
      "url": "https://www.doesmybrandexist.io"
    }
  ],
  "paths": {
    "/api/eclair/v1/scan": {
      "post": {
        "summary": "Scanner une marque ou un domaine",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "entree"
                ],
                "properties": {
                  "entree": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Le site de l'entreprise, sans https:// ni www. — c'est la forme la plus sure : un domaine est unique, un nom de marque peut avoir un homonyme. Un nom seul (« Garage Titi ») est accepte aussi."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Le scan",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Scan"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "cache": {
                          "type": "boolean",
                          "description": "true si le scan avait moins de 24 h et a été resservi sans nouvel appel d'IA."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Corps illisible ou entrée vide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          },
          "429": {
            "description": "Quota de la cle atteint sur 24 h glissantes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          },
          "502": {
            "description": "Aucune IA n'a répondu",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          },
          "503": {
            "description": "Service non configuré",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          },
          "403": {
            "description": "Cle inconnue ou pas encore accordee",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          },
          "401": {
            "description": "Aucune cle dans l en-tete x-api-key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          }
        },
        "description": "Ferme. La cle est exigee dans l en-tete x-api-key : sans elle, 401. Le quota se compte SUR LA CLE et non sur l adresse IP. Une cle se demande sur https://www.doesmybrandexist.io/api-publique",
        "security": [
          {
            "CleApi": []
          }
        ]
      }
    },
    "/api/eclair/v1/s/{jeton}": {
      "get": {
        "summary": "Relire un scan déjà fait",
        "parameters": [
          {
            "name": "jeton",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Le jeton de l'URL de partage /s/{jeton}."
          }
        ],
        "responses": {
          "200": {
            "description": "Le scan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Scan"
                }
              }
            }
          },
          "404": {
            "description": "Scan introuvable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          },
          "401": {
            "description": "Aucune cle dans l en-tete x-api-key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          },
          "403": {
            "description": "Cle inconnue ou pas encore accordee",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erreur"
                }
              }
            }
          }
        },
        "security": [
          {
            "CleApi": []
          }
        ],
        "description": "Ferme, comme le scan. Aucun appel d IA n est fait, donc aucun quota consomme."
      }
    }
  },
  "components": {
    "schemas": {
      "Scan": {
        "type": "object",
        "properties": {
          "marque": {
            "type": "string"
          },
          "secteur": {
            "type": "string",
            "description": "Le secteur d'activité déclaré par les IA, pas saisi par le visiteur."
          },
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Moyenne des scores déclarés par les IA qui ont répondu."
          },
          "branches": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Branche"
            }
          },
          "muettes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Les IA qui n'ont pas répondu."
          },
          "jeton": {
            "type": "string",
            "description": "Identifiant de la page de partage /s/{jeton}."
          }
        }
      },
      "Branche": {
        "type": "object",
        "properties": {
          "ia": {
            "type": "string"
          },
          "modele": {
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "statut": {
            "type": "string",
            "enum": [
              "HIGH",
              "MEDIUM",
              "LOW"
            ]
          },
          "secteur": {
            "type": "string"
          },
          "top": {
            "type": "array",
            "maxItems": 5,
            "items": {
              "type": "string"
            },
            "description": "Les entreprises que cette IA recommande sur ce secteur, demandées à l'aveugle sans nommer la marque."
          },
          "presente": {
            "type": "boolean",
            "description": "La marque figure-t-elle dans ce top 5."
          }
        }
      },
      "Erreur": {
        "type": "object",
        "properties": {
          "erreur": {
            "type": "string"
          }
        }
      }
    },
    "securitySchemes": {
      "CleApi": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Obligatoire. Sans cle, l API rend 401 ; avec une cle inconnue ou pas encore accordee, 403. Elle se demande sur /api-publique et un humain l accorde."
      }
    }
  }
}
