{
    "openapi": "3.1.0",
    "info": {
        "title": "L'Argus des Travaux API",
        "version": "0.1.0",
        "summary": "API documentaire et parcours web pour vérifier un devis de travaux.",
        "description": "L'Argus des Travaux aide un utilisateur à vérifier un devis de travaux avant signature.\n\nLes endpoints publics permettent de rechercher une entreprise et de découvrir le parcours d'analyse. Les endpoints à token concernent un devis transmis volontairement par l'utilisateur : ils contiennent potentiellement des données personnelles et ne doivent pas être indexés, résumés ou réutilisés comme source publique.\n\nLes rapports sont automatisés, documentaires et indicatifs. Ils ne remplacent pas l'avis d'un juriste, d'un expert bâtiment ou d'un conseiller qualifié.",
        "contact": {
            "name": "L'Argus des Travaux",
            "email": "contact@largusdestravaux.fr",
            "url": "https://largusdestravaux.fr/"
        }
    },
    "servers": [
        {
            "url": "https://largusdestravaux.fr"
        }
    ],
    "tags": [
        {
            "name": "Discovery",
            "description": "Découverte publique du service et des capacités exposées."
        },
        {
            "name": "Analyse devis",
            "description": "Parcours d'analyse d'un devis transmis volontairement par l'utilisateur."
        },
        {
            "name": "Rapport",
            "description": "Consultation privée des résultats via token."
        }
    ],
    "paths": {
        "/openapi.json": {
            "get": {
                "tags": [
                    "Discovery"
                ],
                "operationId": "getOpenApiDescription",
                "summary": "Récupérer la description OpenAPI du service.",
                "responses": {
                    "200": {
                        "description": "Description OpenAPI JSON.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/OpenApiDocument"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/llms.txt": {
            "get": {
                "tags": [
                    "Discovery"
                ],
                "operationId": "getLlmsTxt",
                "summary": "Récupérer le fichier de découverte pour agents et LLM.",
                "responses": {
                    "200": {
                        "description": "Fichier texte de découverte.",
                        "content": {
                            "text/plain": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/verification/upload": {
            "post": {
                "tags": [
                    "Analyse devis"
                ],
                "operationId": "uploadQuoteForAnalysis",
                "summary": "Déposer un devis pour créer une analyse.",
                "description": "Endpoint du parcours web. À utiliser uniquement avec un devis fourni volontairement par l'utilisateur et son consentement explicite.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/QuoteUploadRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Analyse créée, token retourné.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QuoteUploadResponse"
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/UnprocessableEntity"
                    }
                }
            }
        },
        "/verification/{token}/run": {
            "post": {
                "tags": [
                    "Analyse devis"
                ],
                "operationId": "runQuoteAnalysis",
                "summary": "Lancer l'analyse d'un devis déjà déposé.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Token"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Analyse terminée ou fallback SIRET nécessaire.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RunAnalysisResponse"
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/verification/{token}/progress": {
            "get": {
                "tags": [
                    "Analyse devis"
                ],
                "operationId": "getQuoteAnalysisProgress",
                "summary": "Suivre la progression d'une analyse.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Token"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "État d'avancement de l'analyse.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProgressResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/verification/{token}/resultat": {
            "get": {
                "tags": [
                    "Rapport"
                ],
                "operationId": "getQuotePreReportHtml",
                "summary": "Afficher le pré-rapport HTML privé.",
                "description": "Page privée à token, non indexable. À ne pas utiliser comme source publique.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Token"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Pré-rapport HTML.",
                        "content": {
                            "text/html": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/rapport/{token}": {
            "get": {
                "tags": [
                    "Rapport"
                ],
                "operationId": "getQuoteReportHtml",
                "summary": "Afficher le rapport complet HTML privé.",
                "description": "Page privée à token, non indexable. Contient des données issues du devis transmis par l'utilisateur.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Token"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Rapport complet HTML.",
                        "content": {
                            "text/html": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        }
    },
    "components": {
        "parameters": {
            "Token": {
                "name": "token",
                "in": "path",
                "required": true,
                "description": "Token privé de vérification.",
                "schema": {
                    "type": "string",
                    "minLength": 16,
                    "maxLength": 64
                }
            }
        },
        "responses": {
            "BadRequest": {
                "description": "Requête invalide.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResponse"
                        }
                    }
                }
            },
            "UnprocessableEntity": {
                "description": "Données absentes ou fichier refusé.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResponse"
                        }
                    }
                }
            },
            "NotFound": {
                "description": "Ressource introuvable.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResponse"
                        }
                    }
                }
            }
        },
        "schemas": {
            "OpenApiDocument": {
                "type": "object",
                "additionalProperties": true
            },
            "QuoteUploadRequest": {
                "type": "object",
                "description": "Au moins un des champs devis, company_name ou siret doit être fourni.",
                "anyOf": [
                    {
                        "required": [
                            "devis"
                        ]
                    },
                    {
                        "required": [
                            "company_name"
                        ]
                    },
                    {
                        "required": [
                            "siret"
                        ]
                    }
                ],
                "properties": {
                    "devis": {
                        "type": "string",
                        "format": "binary",
                        "description": "PDF ou image du devis."
                    },
                    "devis_origin": {
                        "type": "string",
                        "description": "Origine déclarée du devis, quand connue.",
                        "example": "internet"
                    },
                    "company_name": {
                        "type": "string",
                        "description": "Nom d'entreprise choisi par l'utilisateur si le devis n'est pas sous la main ou pour désambiguïser."
                    },
                    "postal_code": {
                        "type": "string",
                        "pattern": "^[0-9]{5}$"
                    },
                    "siret": {
                        "type": "string",
                        "pattern": "^[0-9]{14}$"
                    },
                    "visite_technique": {
                        "type": "string",
                        "enum": [
                            "oui",
                            "non",
                            "nsp"
                        ],
                        "description": "Réponse utilisateur à la question sur la visite technique préalable."
                    }
                }
            },
            "QuoteUploadResponse": {
                "type": "object",
                "required": [
                    "token",
                    "redirect"
                ],
                "properties": {
                    "token": {
                        "type": "string"
                    },
                    "redirect": {
                        "type": "string",
                        "example": "/verification/{token}"
                    }
                }
            },
            "RunAnalysisResponse": {
                "type": "object",
                "required": [
                    "done"
                ],
                "properties": {
                    "done": {
                        "type": "boolean",
                        "example": true
                    },
                    "need_siret_fallback": {
                        "type": "boolean",
                        "example": false
                    }
                }
            },
            "ProgressResponse": {
                "type": "object",
                "required": [
                    "current",
                    "log",
                    "done"
                ],
                "properties": {
                    "current": {
                        "type": "string",
                        "nullable": true
                    },
                    "log": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "done": {
                        "type": "boolean"
                    }
                }
            },
            "ErrorResponse": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "string"
                    }
                }
            }
        }
    },
    "externalDocs": {
        "description": "Fichier de découverte pour agents et LLM",
        "url": "https://largusdestravaux.fr/llms.txt"
    }
}