{"components":{"parameters":{"id":{"in":"path","name":"id","required":true,"schema":{"type":"string"}}},"schemas":{"Definition":{"$ref":"https://tools.bainier.fr/api/v1/schema"},"DraftDefinition":{"$defs":{"input":{"additionalProperties":false,"properties":{"default":{"type":"number"},"hint":{"type":"string"},"id":{"pattern":"^[a-z][a-z0-9_]{0,47}$","type":"string"},"integer":{"type":"boolean"},"label":{"type":"string"},"max":{"type":"number"},"min":{"type":"number"},"unit":{"type":"string"},"units":{"items":{"$ref":"#/components/schemas/DraftDefinition/$defs/unit"},"type":"array"}},"required":["id","label","unit","default","min","max"],"type":"object"},"output":{"additionalProperties":false,"properties":{"formula":{"maxLength":512,"type":"string"},"id":{"pattern":"^[a-z][a-z0-9_]{0,47}$","type":"string"},"label":{"type":"string"},"precision":{"maximum":10,"minimum":0,"type":"integer"},"unit":{"type":"string"}},"required":["id","label","unit","formula"],"type":"object"},"unit":{"additionalProperties":false,"properties":{"factor":{"exclusiveMinimum":0,"type":"number"},"label":{"type":"string"},"offset":{"default":0,"type":"number"}},"required":["label","factor"],"type":"object"}},"$schema":"https://json-schema.org/draft/2020-12/schema","additionalProperties":false,"properties":{"category":{"enum":["electronics","rf","mcu","aquarium","reef","everyday","converters"]},"checks":{"items":{"additionalProperties":false,"properties":{"formula":{"maxLength":512,"type":"string"},"max":{"type":"number"},"message":{"maxLength":400,"type":"string"},"min":{"type":"number"}},"required":["formula","min","max","message"],"type":"object"},"maxItems":12,"type":"array"},"description":{"maxLength":1200,"type":"string"},"explanation":{"items":{"maxLength":1500,"type":"string"},"maxItems":12,"type":"array"},"id":{"pattern":"^[a-z0-9-]{1,70}$","type":"string"},"inputs":{"items":{"$ref":"#/components/schemas/DraftDefinition/$defs/input"},"maxItems":20,"minItems":1,"type":"array"},"notes":{"items":{"type":"string"},"type":"array"},"outputs":{"items":{"$ref":"#/components/schemas/DraftDefinition/$defs/output"},"maxItems":20,"minItems":1,"type":"array"},"section":{"maxLength":80,"type":"string"},"sources":{"items":{"format":"uri","type":"string"},"type":"array"},"tags":{"items":{"type":"string"},"maxItems":10,"type":"array"},"tests":{"items":{"additionalProperties":false,"properties":{"expected":{"additionalProperties":{"type":"number"},"type":"object"},"inputs":{"additionalProperties":{"type":"number"},"type":"object"},"tolerance":{"exclusiveMinimum":0,"maximum":0.001,"type":"number"}},"required":["inputs","expected"],"type":"object"},"maxItems":10,"minItems":0,"type":"array"},"title":{"maxLength":120,"type":"string"},"version":{"const":1},"visuals":{"items":{"additionalProperties":false,"properties":{"caption":{"maxLength":300,"type":"string"},"kind":{"enum":["diagram","curve","bar"]},"x":{"type":"string"},"y":{"type":"string"}},"required":["kind"],"type":"object"},"maxItems":4,"type":"array"}},"required":["version","id","title","description","category","inputs","outputs"],"title":"Calibria Formula v1","type":"object"},"Error":{"properties":{"error":{"type":"string"}},"type":"object"},"Plot":{"additionalProperties":false,"properties":{"max":{"type":"number"},"min":{"type":"number"},"points":{"default":64,"maximum":96,"minimum":2,"type":"integer"},"values":{"additionalProperties":{"type":"number"},"type":"object"},"x":{"type":"string"},"y":{"type":"string"}},"required":["values","x","y","min","max"],"type":"object"},"Proof":{"description":"Payload ALTCHA v2 signé, résolu côté navigateur ; usage unique, but et sujet liés au challenge.","properties":{"challenge":{"type":"object"},"solution":{"properties":{"counter":{"type":"integer"},"derivedKey":{"type":"string"},"time":{"type":"number"}},"required":["counter","derivedKey"],"type":"object"}},"required":["challenge","solution"],"type":"object"},"Save":{"additionalProperties":false,"properties":{"definition":{"$ref":"#/components/schemas/DraftDefinition"},"id":{"type":"string"},"public":{"default":false,"type":"boolean"}},"required":["definition"],"type":"object"},"Values":{"additionalProperties":false,"properties":{"record":{"default":false,"description":"Publier uniquement le nom de l’outil public dans l’activité, pas les valeurs.","type":"boolean"},"values":{"additionalProperties":{"type":"number"},"type":"object"}},"required":["values"],"type":"object"}},"securitySchemes":{"bearerAuth":{"scheme":"bearer","type":"http"},"cookieAuth":{"in":"cookie","name":"calibria","type":"apiKey"},"visitorAuth":{"in":"cookie","name":"calibria_guest","type":"apiKey"}}},"info":{"description":"Recherche, calculs, courbes et créations personnelles Calibria. Lire les unités de référence de chaque définition. Les créations deviennent publiques après validation administrateur.","title":"Calibria API","version":"1.1.0"},"openapi":"3.1.0","paths":{"/api/v1/activity":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"summary":"Outils publics récemment utilisés, sans valeurs ni identité"}},"/api/v1/admin/creations":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"security":[{"bearerAuth":[]},{"cookieAuth":[]}],"summary":"Toutes les créations privées et publiques, administrateur uniquement"}},"/api/v1/admin/creations/{id}/review":{"parameters":[{"$ref":"#/components/parameters/id"}],"post":{"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"decision":{"enum":["approved","rejected","pending"]},"note":{"maxLength":2000,"type":"string"}},"required":["decision"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"security":[{"bearerAuth":[]},{"cookieAuth":[]}],"summary":"Décision administrateur"}},"/api/v1/admin/reports":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"security":[{"bearerAuth":[]},{"cookieAuth":[]}],"summary":"Signalements privés, administrateur uniquement"}},"/api/v1/admin/reports/{id}/review":{"parameters":[{"$ref":"#/components/parameters/id"}],"post":{"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"decision":{"enum":["open","resolved","dismissed"]},"note":{"maxLength":2000,"type":"string"}},"required":["decision"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"security":[{"bearerAuth":[]},{"cookieAuth":[]}],"summary":"Décision administrateur"}},"/api/v1/ai/generate":{"post":{"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"prompt":{"maxLength":1500,"minLength":12,"type":"string"},"proof":{"$ref":"#/components/schemas/Proof"},"website":{"maxLength":0,"type":"string"}},"required":["prompt","proof"],"type":"object"}}},"required":true},"responses":{"200":{"description":"definition, validated, saved=false"},"429":{"description":"Limite de génération"},"503":{"description":"Préparation momentanément indisponible"}},"security":[{"bearerAuth":[]},{"cookieAuth":[]},{"visitorAuth":[]}],"summary":"Préparer une proposition de calculateur sans l’enregistrer"}},"/api/v1/ai/status":{"get":{"responses":{"200":{"description":"État"}},"security":[{"bearerAuth":[]}],"summary":"Disponibilité et quota"}},"/api/v1/auth/login":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"password":{"format":"password","type":"string"},"username":{"type":"string"}},"required":["username","password"],"type":"object"}}},"required":true},"responses":{"200":{"description":"Connecté"},"401":{"description":"Identifiants invalides"}},"summary":"Session navigateur Secure HttpOnly"}},"/api/v1/auth/logout":{"post":{"responses":{"200":{"description":"Déconnecté"}},"summary":"Fermer la session"}},"/api/v1/auth/password":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"current":{"type":"string"},"password":{"minLength":12,"type":"string"}},"required":["current","password"],"type":"object"}}},"required":true},"responses":{"200":{"description":"Reconnectez-vous"}},"security":[{"bearerAuth":[]}],"summary":"Changer le mot de passe, révoquer les sessions navigateur"}},"/api/v1/auth/register":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"invite":{"type":"string"},"password":{"minLength":12,"type":"string"},"username":{"type":"string"}},"required":["username","password","invite"],"type":"object"}}},"required":true},"responses":{"200":{"description":"Compte créé"}},"summary":"Inscription sur invitation"}},"/api/v1/builder/plot":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"definition":{"$ref":"#/components/schemas/DraftDefinition"},"plot":{"$ref":"#/components/schemas/Plot"}},"required":["definition","plot"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"summary":"Courbe d’un calculateur en cours de création"}},"/api/v1/calculators":{"get":{"responses":{"200":{"description":"Liste items"}},"summary":"Catalogue public et créations privées accessibles"},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Save"}}},"required":true},"responses":{"200":{"description":"Identifiant et statut"},"422":{"description":"Définition invalide"}},"security":[{"bearerAuth":[]},{"cookieAuth":[]},{"visitorAuth":[]}],"summary":"Créer ou modifier sa création personnelle ; remise en attente de publication"}},"/api/v1/calculators/{id}":{"delete":{"responses":{"200":{"description":"Supprimée"},"403":{"description":"Interdit"}},"security":[{"bearerAuth":[]}],"summary":"Supprimer sa création et ses révisions"},"get":{"responses":{"200":{"description":"Définition et statut"},"404":{"description":"Ressource invisible"}},"summary":"Définition exportable"},"parameters":[{"$ref":"#/components/parameters/id"}]},"/api/v1/calculators/{id}/evaluate":{"get":{"parameters":[{"explode":true,"in":"query","name":"values","schema":{"additionalProperties":{"type":"number"},"type":"object"},"style":"form"}],"responses":{"200":{"description":"id, results, curated, notes"},"422":{"description":"Entrées invalides"}},"summary":"Calcul GET avec une valeur par paramètre d’entrée, dans ses unités de référence"},"parameters":[{"$ref":"#/components/parameters/id"}],"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Values"}}},"required":true},"responses":{"200":{"description":"Résultats numériques et notes"},"422":{"description":"Hors domaine"}},"summary":"Calcul à partir des entrées canoniques"}},"/api/v1/calculators/{id}/plot":{"parameters":[{"$ref":"#/components/parameters/id"}],"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plot"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"summary":"Échantillonner une courbe ; y=null hors domaine"}},"/api/v1/calculators/{id}/report":{"parameters":[{"$ref":"#/components/parameters/id"}],"post":{"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"kind":{"enum":["formula","units","result","display","other"]},"message":{"maxLength":3000,"minLength":10,"type":"string"},"proof":{"$ref":"#/components/schemas/Proof"},"website":{"maxLength":0,"type":"string"}},"required":["kind","message","proof"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"summary":"Signaler un problème à l’administrateur"}},"/api/v1/calculators/{id}/revisions":{"get":{"responses":{"200":{"description":"Vingt dernières versions"}},"security":[{"bearerAuth":[]}],"summary":"Historique réservé au propriétaire"},"parameters":[{"$ref":"#/components/parameters/id"}]},"/api/v1/challenge":{"get":{"parameters":[{"in":"query","name":"purpose","required":true,"schema":{"enum":["visitor","generation","report"]}},{"description":"ID du calculateur pour un signalement ; vide sinon","in":"query","name":"subject","schema":{"maxLength":70,"type":"string"}}],"responses":{"200":{"description":"Challenge ALTCHA v2, expiration 5 minutes"}},"summary":"Challenge anti-bot ALTCHA local"}},"/api/v1/expression":{"post":{"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"formula":{"maxLength":512,"type":"string"}},"required":["formula"],"type":"object"}}},"required":true},"responses":{"200":{"description":"Résultat numérique"},"422":{"description":"Expression ou résultat invalide"}},"summary":"Calculatrice arithmétique bornée, sans IA"}},"/api/v1/favorites":{"get":{"responses":{"200":{"description":"Identifiants"}},"security":[{"bearerAuth":[]}],"summary":"Favoris"}},"/api/v1/favorites/{id}":{"parameters":[{"$ref":"#/components/parameters/id"}],"post":{"responses":{"200":{"description":"État"}},"security":[{"bearerAuth":[]}],"summary":"Basculer un favori"}},"/api/v1/invites":{"post":{"responses":{"200":{"description":"Code"},"403":{"description":"Interdit"}},"security":[{"bearerAuth":[]}],"summary":"Invitation usage unique 7 jours (admin)"}},"/api/v1/keys":{"get":{"responses":{"200":{"description":"Clés sans secrets"}},"security":[{"bearerAuth":[]}],"summary":"Métadonnées des clés actives"},"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"name":{"maxLength":80,"type":"string"}},"type":"object"}}}},"responses":{"200":{"description":"Clé"}},"security":[{"bearerAuth":[]}],"summary":"Nouvelle clé ; 90 jours ; secret affiché une fois"}},"/api/v1/keys/{id}":{"delete":{"responses":{"200":{"description":"Révoquée"}},"security":[{"bearerAuth":[]}],"summary":"Révoquer sa clé"},"parameters":[{"$ref":"#/components/parameters/id"}]},"/api/v1/meta":{"get":{"responses":{"200":{"description":"Métadonnées"}},"summary":"Catégories et session"}},"/api/v1/preview":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"definition":{"$ref":"#/components/schemas/DraftDefinition"},"values":{"additionalProperties":{"type":"number"},"type":"object"}},"required":["definition","values"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"summary":"Prévisualiser une définition sans compte et sans test obligatoire"}},"/api/v1/schema":{"get":{"responses":{"200":{"description":"Schéma"}},"summary":"Calibria Formula v1 JSON Schema"}},"/api/v1/search":{"get":{"parameters":[{"in":"query","name":"q","schema":{"maxLength":240,"type":"string"}},{"in":"query","name":"category","schema":{"type":"string"}},{"in":"query","name":"section","schema":{"type":"string"}},{"in":"query","name":"mine","schema":{"type":"boolean"}},{"in":"query","name":"sort","schema":{"enum":["","alpha","recent"],"type":"string"}},{"in":"query","name":"limit","schema":{"default":24,"maximum":100,"minimum":1,"type":"integer"}},{"in":"query","name":"offset","schema":{"maximum":100000,"minimum":0,"type":"integer"}}],"responses":{"200":{"description":"items, total, categories, sections, offset, limit"}},"summary":"Recherche tolérante aux fautes, filtres et pagination"}},"/api/v1/validate":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Definition"}}},"required":true},"responses":{"200":{"description":"Tests et valeurs par défaut"},"422":{"description":"Définition invalide"}},"summary":"Valider une définition et ses tests"}},"/api/v1/visitor/start":{"post":{"requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"proof":{"$ref":"#/components/schemas/Proof"},"website":{"maxLength":0,"type":"string"}},"required":["proof"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Résultat JSON"},"400":{"description":"Requête ou vérification incorrecte"},"401":{"description":"Session requise"},"403":{"description":"Accès interdit"},"404":{"description":"Ressource inexistante ou privée"},"422":{"description":"Valeurs ou définition invalides"},"429":{"description":"Limite temporaire"}},"summary":"Créer un espace personnel lié au navigateur, sans compte"}}},"servers":[{"url":"https://tools.bainier.fr"}]}