Repository navigation
Api rest Open3Cl
RedFroggy héberge le moteur Open3CL sous forme d'API REST. Vous envoyez un DPE, l'API le recalcule et vous le renvoie complété des résultats : consommations, émissions, étiquettes.
- Obtenir une clé d'API
- Référence
- Envoyer un DPE JSON ou XML
- Lire le résultat
- Exemples de code : curl, JavaScript / Node.js, Java, Python, PHP, C#, Go
- Erreurs
- Bonnes pratiques
L'API est privée : sans clé valide, chaque appel est rejeté avec une erreur 403.
Pour obtenir une clé, écrivez à contact@redfroggy.fr en précisant votre organisation et l'usage prévu (volume approximatif, intégration serveur, etc.).
La clé est personnelle et secrète. Ne la publiez pas dans un dépôt de code et ne l'utilisez pas dans un navigateur ou une application mobile, où elle serait visible par tous. Appelez l'API depuis votre serveur.
| URL | https://3cl.redfroggy.io/ |
| Méthode | POST |
| Authentification | en-tête X-Auth-Token: <votre clé d'API> |
| Corps | un DPE complet, en JSON ou en XML (format ADEME) |
| Réponse | le DPE recalculé, au même format que la requête |
| Délai maximal | 300 s par appel |
Exemple de réponse 400 :
{ "err": "DPE invalide : Cannot read properties of undefined (reading 'enum_modele_dpe_id')" }
- Gardez la clé côté serveur, dans une variable d'environnement ou un gestionnaire de secrets, jamais dans le code source.
- Prévoyez un délai d'attente long (quelques secondes en temps normal, mais le premier appel après une période d'inactivité peut être plus lent, le temps que l'API démarre).
-
Ne relancez pas en boucle un DPE en erreur
400: le même DPE donnera la même erreur. - Pour des volumes importants (traitement de corpus, appels en masse), prévenez-nous à contact@redfroggy.fr avant de lancer le traitement.
- Pour calculer sans réseau ou intégrer le moteur dans votre application, utilisez directement le paquet npm @open3cl/engine (voir le README).
RedFroggy héberge le moteur Open3CL sous forme d'API REST. Vous envoyez un DPE, l'API le recalcule et vous le renvoie complété des résultats : consommations, émissions, étiquettes.
- [Obtenir une clé d'API](#obtenir-une-clé-dapi)
- [Référence](#référence)
- [Envoyer un DPE JSON ou XML](#envoyer-un-dpe-json-ou-xml)
- [Lire le résultat](#lire-le-résultat)
- [Exemples de code](#exemples-de-code) : [curl](#curl), [JavaScript / Node.js](#javascript--nodejs), [Java](#java), [Python](#python), [PHP](#php), [C#](#c), [Go](#go)
- [Erreurs](#erreurs)
- [Bonnes pratiques](#bonnes-pratiques)
L'API est privée : sans clé valide, chaque appel est rejeté avec une erreur 403.
Pour obtenir une clé, écrivez à [contact@redfroggy.fr](mailto:contact@redfroggy.fr) en précisant votre organisation et l'usage prévu (volume approximatif, intégration serveur, etc.).
La clé est personnelle et secrète. Ne la publiez pas dans un dépôt de code et ne l'utilisez pas dans un navigateur ou une application mobile, où elle serait visible par tous. Appelez l'API depuis votre serveur.
| URL | https://3cl.redfroggy.io/ |
| Méthode | POST |
| Authentification | en-tête X-Auth-Token: <votre clé d'API>
|
| Corps | un DPE complet, en JSON ou en XML (format ADEME) |
| Réponse | le DPE recalculé, au même format que la requête |
| Délai maximal | 300 s par appel |
Le format de la requête est déterminé par l'en-tête Content-Type :
Content-Type de la requête |
Corps attendu | Réponse |
|---|---|---|
application/json |
DPE au format JSON | application/json |
application/xml ou text/xml
|
DPE XML ADEME, tel que téléchargé sur l'[observatoire DPE](https://observatoire-dpe-audit.ademe.fr) | application/xml |
XML : envoyez le fichier XML du DPE tel quel, sans transformation. C'est le plus simple si vous partez d'un DPE de l'observatoire ADEME.
JSON : le DPE doit suivre la structure du XML ADEME, convertie en JSON ({ "numero_dpe": …, "administratif": …, "logement": … }). Les collections sont des tableaux. Des DPE XML d'exemple sont disponibles dans [test/fixtures](https://github.com/Open3CL/engine/tree/main/test/fixtures) du dépôt Open3CL.
Le corps n'est pas validé contre un schéma : un DPE incomplet ou incohérent est rejeté par le moteur avec une erreur 400 (voir [Erreurs](#erreurs)).
Dans tous les exemples, la clé d'API est lue dans la variable d'environnement OPEN3CL_API_KEY :
export OPEN3CL_API_KEY='votre-clé-d-api'DPE JSON :
curl -X POST https://3cl.redfroggy.io/ \
-H "X-Auth-Token: $OPEN3CL_API_KEY" \
-H 'Content-Type: application/json' \
--data @dpe.json \
-o dpe-calcule.jsonDPE XML :
curl -X POST https://3cl.redfroggy.io/ \
-H "X-Auth-Token: $OPEN3CL_API_KEY" \
-H 'Content-Type: application/xml' \
--data-binary @dpe.xml \
-o dpe-calcule.xmlPour un fichier XML, utilisez --data-binary et pas --data : ce dernier supprime les retours à la ligne.
Afficher directement l'étiquette avec [jq](https://jqlang.org/) :
curl -s -X POST https://3cl.redfroggy.io/ \
-H "X-Auth-Token: $OPEN3CL_API_KEY" \
-H 'Content-Type: application/json' \
--data @dpe.json \
| jq '.logement.sortie.ep_conso | {classe_bilan_dpe, ep_conso_5_usages_m2}'Node.js 18 ou plus récent (fetch natif), sans dépendance.
DPE JSON :
import { readFile } from 'node:fs/promises';
const dpe = JSON.parse(await readFile('dpe.json', 'utf-8'));
const response = await fetch('https://3cl.redfroggy.io/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': process.env.OPEN3CL_API_KEY
},
body: JSON.stringify(dpe)
});
if (!response.ok) {
throw new Error(`Open3CL ${response.status} : ${await response.text()}`);
}
const result = await response.json();
const { classe_bilan_dpe, ep_conso_5_usages_m2 } = result.logement.sortie.ep_conso;
console.log(`Étiquette ${classe_bilan_dpe} (${ep_conso_5_usages_m2} kWhEP/m²/an)`);DPE XML :
import { readFile, writeFile } from 'node:fs/promises';
const response = await fetch('https://3cl.redfroggy.io/', {
method: 'POST',
headers: {
'Content-Type': 'application/xml',
'X-Auth-Token': process.env.OPEN3CL_API_KEY
},
body: await readFile('dpe.xml', 'utf-8')
});
if (!response.ok) {
throw new Error(`Open3CL ${response.status} : ${await response.text()}`);
}
await writeFile('dpe-calcule.xml', await response.text());Java 11 ou plus récent (java.net.http.HttpClient), sans dépendance. Le fichier est envoyé tel quel, que ce soit du JSON ou du XML.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
import java.time.Duration;
public class Open3clClient {
private static final URI API_URL = URI.create("https://3cl.redfroggy.io/");
private final HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
private final String apiKey = System.getenv("OPEN3CL_API_KEY");
/** contentType : "application/json" ou "application/xml" */
public String calculate(Path dpeFile, String contentType) throws Exception {
HttpRequest request = HttpRequest.newBuilder(API_URL)
.timeout(Duration.ofMinutes(5))
.header("Content-Type", contentType)
.header("X-Auth-Token", apiKey)
.POST(HttpRequest.BodyPublishers.ofFile(dpeFile))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IllegalStateException("Open3CL " + response.statusCode() + " : " + response.body());
}
return response.body();
}
public static void main(String[] args) throws Exception {
Open3clClient open3cl = new Open3clClient();
String json = open3cl.calculate(Path.of("dpe.json"), "application/json");
String xml = open3cl.calculate(Path.of("dpe.xml"), "application/xml");
System.out.println(json.length() + " / " + xml.length());
}
}Pour lire le JSON renvoyé, utilisez la bibliothèque de votre projet (Jackson, par exemple) :
JsonNode epConso = new ObjectMapper().readTree(json).at("/logement/sortie/ep_conso");
String classe = epConso.get("classe_bilan_dpe").asText();Avec [requests](https://requests.readthedocs.io/) (pip install requests).
DPE JSON :
import json
import os
import requests
API_URL = "https://3cl.redfroggy.io/"
HEADERS = {"X-Auth-Token": os.environ["OPEN3CL_API_KEY"]}
with open("dpe.json", encoding="utf-8") as f:
dpe = json.load(f)
response = requests.post(API_URL, json=dpe, headers=HEADERS, timeout=300)
response.raise_for_status()
ep_conso = response.json()["logement"]["sortie"]["ep_conso"]
print(f"Étiquette {ep_conso['classe_bilan_dpe']} ({ep_conso['ep_conso_5_usages_m2']} kWhEP/m²/an)")DPE XML :
with open("dpe.xml", "rb") as f:
response = requests.post(
API_URL,
data=f,
headers={**HEADERS, "Content-Type": "application/xml"},
timeout=300,
)
response.raise_for_status()
with open("dpe-calcule.xml", "w", encoding="utf-8") as f:
f.write(response.text)Avec l'extension cURL.
<?php
function open3cl_calculate(string $file, string $contentType): string
{
$ch = curl_init('https://3cl.redfroggy.io/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => file_get_contents($file),
CURLOPT_HTTPHEADER => [
'Content-Type: ' . $contentType,
'X-Auth-Token: ' . getenv('OPEN3CL_API_KEY'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 300,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("Open3CL $status : $body");
}
return $body;
}
$result = json_decode(open3cl_calculate('dpe.json', 'application/json'), true);
echo $result['logement']['sortie']['ep_conso']['classe_bilan_dpe'], PHP_EOL;
file_put_contents('dpe-calcule.xml', open3cl_calculate('dpe.xml', 'application/xml'));.NET 6 ou plus récent.
using System.Net.Http.Headers;
using System.Text.Json;
using var http = new HttpClient { Timeout = TimeSpan.FromMinutes(5) };
http.DefaultRequestHeaders.Add("X-Auth-Token", Environment.GetEnvironmentVariable("OPEN3CL_API_KEY"));
async Task<string> CalculateAsync(string file, string contentType)
{
var content = new StreamContent(File.OpenRead(file));
content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
var response = await http.PostAsync("https://3cl.redfroggy.io/", content);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException($"Open3CL {(int)response.StatusCode} : {body}");
return body;
}
var json = await CalculateAsync("dpe.json", "application/json");
var classe = JsonDocument.Parse(json).RootElement
.GetProperty("logement").GetProperty("sortie")
.GetProperty("ep_conso").GetProperty("classe_bilan_dpe").GetString();
Console.WriteLine($"Étiquette {classe}");
await File.WriteAllTextAsync("dpe-calcule.xml", await CalculateAsync("dpe.xml", "application/xml"));Bibliothèque standard uniquement.
package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func calculate(file, contentType string) ([]byte, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
req, err := http.NewRequest(http.MethodPost, "https://3cl.redfroggy.io/", f)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", contentType)
req.Header.Set("X-Auth-Token", os.Getenv("OPEN3CL_API_KEY"))
client := &http.Client{Timeout: 5 * time.Minute}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("open3cl %d : %s", resp.StatusCode, body)
}
return body, nil
}
func main() {
xml, err := calculate("dpe.xml", "application/xml")
if err != nil {
panic(err)
}
os.WriteFile("dpe-calcule.xml", xml, 0o644)
}| Code | Cause | Que faire |
|---|---|---|
200 |
DPE recalculé | — |
400 |
Corps illisible (JSON ou XML mal formé) ou DPE rejeté par le moteur (donnée obligatoire manquante, valeur incohérente…) | Le message est dans le champ err de la réponse, toujours en JSON. Vérifiez le DPE envoyé. |
403 |
En-tête X-Auth-Token absent, clé invalide ou révoquée |
Vérifiez la clé ; en cas de doute, écrivez à [contact@redfroggy.fr](mailto:contact@redfroggy.fr). |
404 |
URL autre que https://3cl.redfroggy.io/
|
Appelez la racine /, sans chemin. |
405 |
Méthode autre que POST
|
Utilisez POST. |
Exemple de réponse 400 :
{ "err": "DPE invalide : Cannot read properties of undefined (reading 'enum_modele_dpe_id')" }- Gardez la clé côté serveur, dans une variable d'environnement ou un gestionnaire de secrets, jamais dans le code source.
- Prévoyez un délai d'attente long (quelques secondes en temps normal, mais le premier appel après une période d'inactivité peut être plus lent, le temps que l'API démarre).
-
Ne relancez pas en boucle un DPE en erreur
400: le même DPE donnera la même erreur. - Pour des volumes importants (traitement de corpus, appels en masse), prévenez-nous à [contact@redfroggy.fr](mailto:contact@redfroggy.fr) avant de lancer le traitement.
- Pour calculer sans réseau ou intégrer le moteur dans votre application, utilisez directement le paquet npm [@open3cl/engine](https://www.npmjs.com/package/@open3cl/engine) (voir le [README](https://github.com/Open3CL/engine#readme)).