{"openapi":"3.1.0","info":{"title":"API de Grammage","version":"1","description":"Enregistre les résultats mesurés et signés par une CI Grammage sous licence, les fait remesurer par Solyzon, et publie les attestations que vérifie le badge."},"servers":[{"url":"https://api.getgrammage.com"}],"components":{"securitySchemes":{"licence":{"type":"http","scheme":"bearer","description":"jeton grammage2"}},"schemas":{"Problem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"}}},"Recorded":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"verification":{"type":"string","enum":["pending","passed","failed","error"],"description":"la mesure de Solyzon, dont dépend l’attestation : en attente, conforme au rapport, plus de 20 % plus lourde, ou impossible"},"attestation":{"type":["string","null"],"description":"JWS compact, EdDSA, une fois la vérification conforme"},"expiresAt":{"type":["string","null"],"format":"date-time"}}}}},"paths":{"/v1/results":{"post":{"summary":"Enregistrer un résultat signé","security":[{"licence":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["report"],"properties":{"report":{"type":"string","description":"texte exact du rapport JSON"}}}}}},"responses":{"200":{"description":"Déjà enregistré avec cette clé d’idempotence"},"202":{"description":"Enregistré, en attente de la mesure de Solyzon","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recorded"}}}},"400":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/certifications":{"post":{"summary":"Faire mesurer et certifier un domaine par Solyzon, sans CI","description":"Réservé aux licences badge, une fois par domaine tous les 7 jours, dans le quota mensuel de pages de la licence.","security":[{"licence":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","scope","category"],"properties":{"url":{"type":"string","format":"uri"},"scope":{"type":"string","enum":["page","site"]},"category":{"type":"string","enum":["auto","presentation","documentation","showcase","editorial","ecommerce","application"]},"device":{"type":"string","enum":["mobile","desktop"],"default":"mobile"},"mode":{"type":"string","enum":["fast","normal","full"],"default":"normal","description":"1, 2 ou 3 passages par page"},"maxPages":{"type":"integer","minimum":1,"maximum":100,"default":50},"originCountry":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"pays du serveur d’origine en code ISO, pris en compte seulement quand le site passe par un CDN"}}}}}},"responses":{"202":{"description":"Mis en file, la mesure de Solyzon fera naître l’attestation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recorded"}}}},"400":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/tests":{"post":{"summary":"Tester une page gratuitement, sans licence","description":"Une page en un passage, catégorie auto par défaut, trois tests par jour et par domaine, dix par adresse. La même page mesurée il y a moins de 4 heures rend le résultat existant, en 200, et passé ce délai le dernier résultat reste rendu quand une limite bloque la remesure.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"device":{"type":"string","enum":["mobile","desktop"]},"category":{"type":"string","enum":["auto","presentation","documentation","showcase","editorial","ecommerce","application"]}}}}}},"responses":{"200":{"description":"La même page, déjà mesurée il y a moins de 4 heures"},"202":{"description":"Mis en file, suivre /v1/tests/{id} ou ses événements"},"400":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/tests/{id}":{"get":{"summary":"Lire un test gratuit, son état puis son rapport complet","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"status, queuePosition, progress, detail, failure ({ code, message, retryable, httpStatus, vendor }) sur un échec, report une fois passed, et reportPdf (true quand le rapport PDF est prêt)"},"404":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/tests/{id}/report.pdf":{"get":{"summary":"Télécharger le rapport PDF d’un test gratuit mesuré","description":"Un rapport non signé, titré « Rapport de test gratuit », qui n’est pas une attestation confirmée. Conservé 30 jours avec le test.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"application/pdf, en pièce jointe grammage-<domaine>-<AAAA-MM-JJ>.pdf"},"404":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/tests/{id}/events":{"get":{"summary":"Suivre un test gratuit en temps réel, en Server-Sent Events","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"text/event-stream, un événement JSON par changement"},"404":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/tests/{id}/brief":{"get":{"summary":"Lire le brief d’un test mesuré, en Markdown","description":"format=agent donne le brief de correction pour un agent de code, format=rgesn l’aide à la déclaration d’écoconception.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"format","in":"query","schema":{"type":"string","enum":["agent","rgesn"],"default":"agent"}}],"responses":{"200":{"description":"text/markdown"},"400":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/tests/{id}/cancel":{"post":{"summary":"Annuler un test gratuit","description":"Le test sort de la file, ou le rapport du worker est ignoré s’il est déjà mesuré, et reste compté dans les limites du jour. Annuler deux fois répond pareil.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"{ id, status: cancelled }"},"404":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/version":{"get":{"summary":"La version de l’API et du moteur","description":"name, service, version du moteur, api, schemaVersion du rapport, et les adresses du contrat et de la documentation.","responses":{"200":{"description":"application/json"}}}},"/v1/results/{id}/events":{"get":{"summary":"Suivre une mesure en temps réel, en Server-Sent Events","description":"Un événement JSON à chaque changement : status, queuePosition, progress (step discovery, measure ou report, page, pages, run, runs, url) et detail. Le flux se ferme au verdict.","security":[{"licence":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Flux ouvert","content":{"text/event-stream":{}}},"401":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/results/{id}":{"get":{"summary":"Relire un résultat et son rapport détaillé","security":[{"licence":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Le résultat, l’état de sa vérification, son attestation et son rapport détaillé"},"401":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/attestations/{host}":{"get":{"summary":"L’attestation en cours d’un site, ou d’une page avec path","parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"}},{"name":"path","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"L’attestation"},"404":{"description":"Erreur","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}}}